Pyform dynamic styling does not take an effect - python

I started pyforms yesterday and it looks like many parts of the framework is not documented yet.
I write an application which requires a style change on demand. I insist on using ControlButton.style and not a CSS file. The documentation does not provide how to use style property and my try failed. It does not make any effect.
from pyforms.basewidget import BaseWidget
from pyforms.controls import ControlText
from pyforms.controls import ControlButton
import os
class GUI(BaseWidget):
def __init__(self, *args, **kwargs):
super().__init__('A test')
self.set_margin(10)
self._directory = ControlText('Directory')
self._directory.value = 'C:\\'
self._directory.changed_event = self.referesh_check
self._ok = ControlButton('OK')
self._formset = [ ('_directory', ' ', '_ok') ]
self.referesh_check()
def referesh_check(self):
dirpath = self._directory.value
if os.path.exists(dirpath):
print('found: ', dirpath)
self._directory.style='color:green'
else:
print('not found: ', dirpath)
self._directory.style='color:red'
pass
if __name__ == '__main__':
from pyforms import start_app
start_app(GUI)
Note:
Using style as method fails with an error
self._directory.style('background-color:green')
AttributeError: 'ControlText' object has no attribute 'style'

Related

PyQgis: item is not the expected type on a QgsMapCanvas

I am currently working on a PyQgis based standalone application and I need to add various QgsRubberBand to my Canvas.
I made a subclass of it : LineAnnotation.
The problem is that when I use the method "QgsMapCanvas.itemAt(event.pos() )" on a "canvasPressEvent", it returns a "qgis._gui.QgsRubberBand" object, not a "LineAnnotation".
Did I do something wrong ? The rest of my program can't work if it doesn't recognize that it's a LineAnnotation as it contains several new methods that I need to use.
Also I can't interact with the item at all, if I try to use one of the methods from QgsRubberBand, the application crashes.
Here is the code with the problem:
from qgis.gui import QgsMapCanvas, QgsLayerTreeMapCanvasBridge, QgsRubberBand
from qgis.core import QgsApplication, QgsProject, QgsPointXY, QgsGeometry
from qgis.PyQt.QtGui import QColor
import sys
class LineAnnotation(QgsRubberBand):
def __init__(self, canvas):
QgsRubberBand.__init__(self, canvas)
self.setColor(QColor("red") )
self.setWidth(10)
class Interface(QgsMapCanvas):
def __init__(self):
QgsMapCanvas.__init__(self)
self.setCanvasColor(QColor("#182F36") )
project_path = "project_path"
project = QgsProject.instance()
project.read(project_path)
layer_tree = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas=self)
layer_tree.setAutoSetupOnFirstLayer(False)
self.zoomToFeatureExtent(project.mapLayersByName('layer_name')[0].extent() )
self.enableAntiAliasing(True)
self.setAcceptDrops(True)
self.setParallelRenderingEnabled(True)
p1 = QgsPointXY(524670.46860305720474571, 5470375.41737424582242966)
p2 = QgsPointXY(589864.10151600651443005, 5487531.63656186405569315)
r = LineAnnotation(self)
r.setToGeometry(QgsGeometry.fromPolylineXY([p1, p2]) )
def mousePressEvent(self, event) -> None:
item = self.itemAt(event.pos() )
print(type(item) )
# Output is "<class 'qgis._gui.QgsRubberBand'>"
# Expected: "<class 'LineAnnotation'>"
class StackOverflow:
def __init__(self):
qgs = QgsApplication([], True)
qgs.setDoubleClickInterval(250)
qgs.initQgis()
graphicUI = Interface()
graphicUI.showMaximized()
sys.exit(qgs.exec_() )
if __name__ == '__main__':
app = StackOverflow()
> output: \<class 'qgis.\_gui.QgsRubberBand'\>
> Desired output: \<class 'lineAnnotation.LineAnnotation'\>
Problem seems to occur in versions prior to Qgis 3.26, my problem was solved after updating to latest version (3.28).

How to create a custom analyzer in Pylucene 8.6.1?

I have looked at this, this and this but I'm not sure why they don't work for me.
I would normally use an analyzer like below.
import lucene
from org.apache.lucene.analysis.core import WhitespaceAnalyzer
from org.apache.lucene.index import IndexWriterConfig, IndexWriter
from org.apache.lucene.store import SimpleFSDirectory
from java.nio.file import Paths
from org.apache.lucene.document import Document, Field, TextField
index_path = "./index"
lucene.initVM()
analyzer = WhitespaceAnalyzer()
config = IndexWriterConfig(analyzer)
store = SimpleFSDirectory(Paths.get(index_path))
writer = IndexWriter(store, config)
doc = Document()
doc.add(Field("title", "The quick brown fox.", TextField.TYPE_STORED))
writer.addDocument(doc)
writer.close()
store.close()
Instead of the WhitespaceAnalyzer() I would like to use MyAnalyzer() which should have LowerCaseFilter and WhitespaceTokenizer.
from org.apache.lucene.analysis.core import LowerCaseFilter, WhitespaceTokenizer
from org.apache.pylucene.analysis import PythonAnalyzer
class MyAnalyzer(PythonAnalyzer):
def __init__(self):
PythonAnalyzer.__init__(self)
def createComponents(self, fieldName):
# What do I write here?
Can you please help me write and use MyAnalyzer()?
I found here and here that the below works.
from org.apache.lucene.analysis.core import LowerCaseFilter, WhitespaceTokenizer
from org.apache.pylucene.analysis import PythonAnalyzer
from org.apache.lucene.analysis import Analyzer
class MyAnalyzer(PythonAnalyzer):
def __init__(self):
PythonAnalyzer.__init__(self)
def createComponents(self, fieldName):
source = WhitespaceTokenizer()
result = LowerCaseFilter(source)
return Analyzer.TokenStreamComponents(source, result)
It would be great if someone can point me in the right direction to be able to find these answer correctly.

How to add dividers to rumps menu

I have made a python script which creates a MacOS Status bar item which displays youtube statistics.
I want to add dividers to the drop down menu when you click the text but I am unable to do this. (Image of what I mean under the text). I have found many examples but all of them only work with an __init__ function in the class. If I try adding an __init__ function to the class I get an error saying AttributeError: 'Sub_Counter' object has no attribute '_menu'. Why is this happening and how can it be fixed?
Code I added to the __init_ function
self.menu = [
"About",
"No Icon",
None,
"Detailed Statistics:",
None,
"Quit",
]
Normal Code without the __init__ function
import rumps
import time
import sys
import os
from sty import fg
from googleapiclient.discovery import build
key = open(os.path.join(sys.path[0], './key.txt')).read().strip()
service = build('youtube', 'v3', developerKey=key)
subs = service.channels().list(
part='statistics',
id='UCERizKQbgpBXOck0R6t_--Q'
).execute()['items'][0]['statistics']['subscriberCount']
timers = ["1 secs","5 secs","10 secs","15 secs","20 secs","25 secs","30 secs","35 secs","45 secs","50 secs","1 Min"]
EXEC_TIMER = 60
class Sub_Counter(rumps.App):
#rumps.timer(EXEC_TIMER)
def pull_data(self, _):
self.sub_menu = timers
subs = service.channels().list(
part='statistics',
id='UCERizKQbgpBXOck0R6t_--Q'
).execute()['items'][0]['statistics']['subscriberCount']
a = (str(subs))
self.icon = "logo.png"
self.title = "Subscribers: " + str(a)
self.notification = str(a) + " Subscribers"
#rumps.clicked("About")
def about(self, _=):
rumps.notification("Youtube Subscriber Count", "Made by Roxiun using Python & rumps", "Shows Youtube Subscriber counts")
#rumps.clicked("No Icon")
def noicon(self, sender):
sender.state = not sender.state
self.icon = None
#rumps.clicked("Detailed Statistics")
def Detailed_Statistics(self, _):
rumps.notification("You have:", self.notification , "Veiws Comming Soon")
if __name__ == "__main__":
Sub_Counter("Loading...").run() #debug=True
Image of what I want to do [circled in red - (Yes it is the line)]
Thanks in advance!
Fixed by doing
app = Sub_Counter("Loading...")
app.menu[
"About",
"No Icon",
None,
"Detailed Statistics:",
None,
"Quit",
]
app.run()
You can add a separator by doing:
self.menu.add(rumps.separator)
Link to source code.

Debugging OOo UNO-Python

I'm trying read and parse a CSV file in LibreOffice Calc. I need to show text in order to debug my logic, and the first thing I found was this. Annoyingly, it duplicates functionality that's built into OOo Basic. The first implementation tries to use a non-existent function; the second one works if I invoke it directly (using TestMessageBox from the Tools menu), but when I include it from my pythonpath directory I get an error:
com.sun.star.uno.RuntimeExceptionError during invoking function main
in module
file:///C:/path/to/test.py
(: 'module' object has no attribute
'MessageBox' C:\path\to\test.py:34
in function main() [msgbox.MessageBox(parentwin, message, 'Title')]
C:\Program Files (x86)\LibreOffice 5\program\pythonscript.py:870 in
function invoke() [ret = self.func( *args )] )
Why is there no attribute MessageBox?
I'm invoking it like this:
import msgbox
def main():
doc = XSCRIPTCONTEXT.getDocument()
parentwin = doc.CurrentController.Frame.ContainerWindow
message = "Message"
msgbox.MessageBox(parentwin, message, 'Title')
return
And here's pythonpath/msgbox.py:
import uno
from com.sun.star.awt.MessageBoxButtons import BUTTONS_OK, BUTTONS_OK_CANCEL, BUTTONS_YES_NO, BUTTONS_YES_NO_CANCEL, BUTTONS_RETRY_CANCEL, BUTTONS_ABORT_IGNORE_RETRY
from com.sun.star.awt.MessageBoxButtons import DEFAULT_BUTTON_OK, DEFAULT_BUTTON_CANCEL, DEFAULT_BUTTON_RETRY, DEFAULT_BUTTON_YES, DEFAULT_BUTTON_NO, DEFAULT_BUTTON_IGNORE
from com.sun.star.awt.MessageBoxType import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
def TestMessageBox():
doc = XSCRIPTCONTEXT.getDocument()
parentwin = doc.CurrentController.Frame.ContainerWindow
s = "This a message"
t = "Title of the box"
res = MessageBox(parentwin, s, t, QUERYBOX, BUTTONS_YES_NO_CANCEL + DEFAULT_BUTTON_NO)
s = res
MessageBox(parentwin, s, t, "infobox")
# Show a message box with the UNO based toolkit
def MessageBox(ParentWin, MsgText, MsgTitle, MsgType=MESSAGEBOX, MsgButtons=BUTTONS_OK):
ctx = uno.getComponentContext()
sm = ctx.ServiceManager
sv = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx)
myBox = sv.createMessageBox(ParentWin, MsgType, MsgButtons, MsgTitle, MsgText)
return myBox.execute()
g_exportedScripts = TestMessageBox,
The package name msgbox is already used in UNO. See msgbox.MsgBox. Choose a different name for your module instead, such as mymsgbox.py. Even better, move it to a package (subdirectory) inside pythonpath, such as mystuff.msgbox.MessageBox.
As a matter of fact, I tried msgbox.MsgBox just now and it seemed like it could be useful:
import msgbox
def main():
message = "Message"
myBox = msgbox.MsgBox(XSCRIPTCONTEXT.getComponentContext())
myBox.addButton("oK")
myBox.renderFromButtonSize()
myBox.numberOflines = 2
myBox.show(message,0,"Title")

Python + Pyglet Cocos2D: TypeError: 'class' object is not callable

I've been working on a tiled map renderer, and I've tried to make a seperate Class in another file. I get this error message:
Type Error: 'renderer' object is not callable
Here's the render.py file:
import pyglet, json
from pyglet.window import key
from pyglet.gl import *
from ConfigParser import SafeConfigParser
from cocos.layer import *
from cocos.batch import *
from cocos.sprite import Sprite
class renderer( Layer ):
def __init__(self, mapname):
super( renderer, self ).__init__()
parser = SafeConfigParser()
try:
world = parser.read('maps/'+mapname+'.txt')
print world
except IOError:
print("No world file!")
return
layer = json.loads(parser.get('layer1', 'map'))
tiletype = parser.get('type', 'tile')
print tiletype
tilesize = 64
for x in range(0, len(layer)):
for y in range(0, len(layer[x])):
self.spr = Sprite("image/tiles/"+tiletype+"/"+str(layer[x][y])+".png")
self.spr.position = ((x+1)*tilesize, (y+1)*tilesize)
self.add(self.spr)
And this is the piece of code I call it with:
from other.render import renderer
 
world = renderer('buildnew')
world()
File Structure:
game/main.py
game/other/render.py
What am I doing wrong?
world = renderer('buildnew')
world()
First you make an instance of the renderer class and store it to world.
But then you write world(), which is wrong cause this object is not callable.
If you want to make world a callable object, you should implement the __call__ method in the renderer class.

Categories