Update Text Entity in Ursina, Python - python

I have this code:
BUTTON_INDENT = -1
class TIME(Text):
def __init__(self):
super().__init__(
text=time.strftime("%H:%M"),
position=(0,0,BUTTON_INDENT),
)
How do I make it so the text inside changes?
I have tried this before too:
BUTTON_INDENT = -1
class TIME(Text):
def __init__(self):
super().__init__(
text=time.strftime("%H:%M"),
position=(0,0,BUTTON_INDENT)
)
def update(self):
self.text = time.strftime("%H:%M")
That doesn't seem to make the text change either.

Anyhow, the update function doesn't work in Text class, here is the full updated code :
from ursina import *
app = Ursina()
BUTTON_INDENT = -1
class TIME(Text):
def __init__(self):
super().__init__()
self.text=time.strftime("%H:%M:%S")
self.position=(0,0,BUTTON_INDENT)
t = TIME()
def update():
t.text = time.strftime("%H:%M:%S")
app.run()

Related

Mouse not drawing in pyglet

My custom mouse image is not showing up in pyglet. It loads normally(When you create the window outside a class), but when i make the window in a class and try yo add the custom mouse cursor nothing happens
class x:
def __init__(self):
self.game_window = pyglet.window.Window()
self.on_mouse_press = self.game_window.event(self.on_mouse_press)
self.game_cursor = pyglet.image.load('image.png')
self.cursor = pyglet.window.ImageMouseCursor(self.game_cursor, 50, 70)
self.game_window.set_mouse_cursor(self.cursor)
I have tried printing every one of the lines of code (for mouse image loading)
When i print - self.game_cursor = pyglet.image.load('image.png') - This is the result:
ImageData 85x82
When i print - self.cursor = pyglet.window.ImageMouseCursor(self.game_cursor, 50, 70) - This is the result:
pyglet.window.ImageMouseCursor object at 0x7f4dad76b390
When i print - self.game_window.set_mouse_cursor(self.cursor) - This is the result:
None
How do I fix make the mouse show?
I strongly suggest you inherit the window class in to your class instead of keeping it as a internal value if possible. So you can use override hooks to replace the on_ functions. Perhaps this is an outdated approach, but for the time I've learned to work with these things - it's reommended.
class x(pyglet.window.Window):
def __init__(self):
super(x, self).__init__()
self.game_cursor = pyglet.image.load('image.png')
self.cursor = pyglet.window.ImageMouseCursor(self.game_cursor, 50, 70)
self.set_mouse_cursor(self.cursor)
def on_mouse_press():
# Your code handling on_mouse_press
Here's a working example:
from pyglet import *
from pyglet.gl import *
key = pyglet.window.key
class main(pyglet.window.Window):
def __init__ (self, width=800, height=600, fps=False, *args, **kwargs):
super(main, self).__init__(width, height, *args, **kwargs)
self.game_cursor = pyglet.image.load('image.png')
self.cursor = pyglet.window.ImageMouseCursor(self.game_cursor, 50, 70)
self.set_mouse_cursor(self.cursor)
self.x, self.y = 0, 0
self.keys = {}
self.mouse_x = 0
self.mouse_y = 0
self.alive = 1
def on_draw(self):
self.render()
def on_close(self):
self.alive = 0
def on_mouse_motion(self, x, y, dx, dy):
self.mouse_x = x
def on_key_release(self, symbol, modifiers):
try:
del self.keys[symbol]
except:
pass
def on_key_press(self, symbol, modifiers):
if symbol == key.ESCAPE: # [ESC]
self.alive = 0
self.keys[symbol] = True
def render(self):
self.clear()
## Add stuff you want to render here.
## Preferably in the form of a batch.
self.flip()
def run(self):
while self.alive == 1:
self.render()
# -----------> This is key <----------
# This is what replaces pyglet.app.run()
# but is required for the GUI to not freeze
#
event = self.dispatch_events()
if __name__ == '__main__':
x = main()
x.run()
According to pyglet documentation for ImageMouseCursor class link method draw(x, y) is abstract. So I've tried sub-classing ImageMouseCursor and implementing draw method like this:
import pyglet
pyglet.resource.path = ['resources']
pyglet.resource.reindex()
# subclass definition
class GameMouse(pyglet.window.ImageMouseCursor):
# class initialization
def __init__(self):
self.game_cursor = pyglet.resource.image('game_cursor.png')
super().__init__(self.game_cursor, 0, 34)
# method override
def draw(self, x, y):
self.game_cursor.blit(x, y)
However, this will not work if gl blending is not enabled. gl blending is needed to display alpha channels. I've managed to enable it by sub-classing Window class, and using glEnable / glBlendFunc functions. This is the part of the code that does as described:
# subclass definition:
class GameApp(pyglet.window.Window):
# class initialization
def __init__(self):
super(GameApp, self).__init__()
pyglet.gl.glEnable(pyglet.gl.GL_BLEND)
pyglet.gl.glBlendFunc(pyglet.gl.GL_SRC_ALPHA,
pyglet.gl.GL_ONE_MINUS_SRC_ALPHA)
Hope this helps

How do i pass a class variable to another class?

I'm making a barcode generator. I need the input in class GUI to be read by class Barcode so it can print the lines on the canvas.
from tkinter import *
class GUI(Frame):
def __init__(self, master=None):
...
self.code_input = Entry(master)
self.code_input.pack()
self.code = self.code_input.get()
...
self.barcode = Barcode(master, height=250, width=200)
self.barcode.pack()
self.barcode.draw()
....
class Barcode(Canvas):
def draw(self):
self.ean = GUI.code
If I reference directly like the above it says AttributeError: type object 'GUI' has no attribute 'code'
If I do inheritance method (based on https://stackoverflow.com/a/19993844/10618936),class Barcode(Canvas, GUI) it says the same as the previous
If I use setter and getter methods:
class GUI(Frame)
def __init__(self, master=None):
...
#property
def code(self):
return self.__code
#code.setter
def code(self, code):
self.__code = code
then self.ean = GUI.code, it won't run the program and say
TypeError: 'property' object is not subscriptable instead
how do I fix this problem? Is the structure of my program really bad? I'm really not good at programming at all... I just want the variable in GUI to be transferred to class Barcode so it can compute and return the result back to GUI to display the barcode
You need to create an instance of the GUI, otherwise you are just referencing to the static class for which code is not defined. You could access it like in this example
class A():
def __init__(self):
self.code = "A"
class B():
def __init__(self):
self.code = "B"
def foo(self):
print(self.code + A().code)
b = B()
b.foo() # Outputs "BA"
Otherwise, to access it like an static variable within the class you need to define it inside the class root level
class A():
code = "C"
def __init__(self):
self.code = "A"
class B():
def __init__(self):
self.code = "B"
def foo(self):
print(self.code + A.code)
b = B()
b.foo() # Outputs "BC"
You should pass the GUI object to the Barcode class, which at the point you create the Barcode instance is self. If you want the Barcode to be inside the GUI frame, you can also directly use it as the Canvas master.
Another thing to notice is that with the way you have it now, self.code will be and remain an empty string, since you only define it right after you've created the Entry widget, at which point it is empty. You should use get on the Entry at the time you want to do something with the contents at that point.
from tkinter import *
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.code_input = Entry(self)
self.code_input.pack()
self.barcode = Barcode(self, height=250, width=200)
self.barcode.pack()
Button(self, text="Update Barcode", command=self.barcode.draw).pack()
class Barcode(Canvas):
def __init__(self, master, height, width):
Canvas.__init__(self, master, height=height, width=width)
self.master = master
self.text = self.create_text((100,100))
def draw(self):
self.itemconfig(self.text, text=self.master.code_input.get())
root = Tk()
gui = GUI(root)
gui.pack()
root.mainloop()
For illustration purposes I create a text object on the canvas and update that with the current value of the Entry on a Button click.

How to transfer a list of element from a screen to another using Kivy

I have some trouble to transfert a list of element, that i get from a file (in the first screen), to the second and third screen.
I have 3 Screen managed by ScreenManager, every screen is in a different file.py and have a file.kv.
This is what my ScreenManager looks like (filename : login.py):
from interface1 import Interface1App
from interface2 import Interface2App
class LoginApp(App):
def build(self):
manager = ScreenManager()
#add view login
manager.add_widget(Login(name='login'))
# add view 'interface1'
app = Interface1App()
app.load_kv()
interfacen1 = app.build()
manager.add_widget(interfacen1)
# add view 'interface2'
app2 = Interface2App()
app2.load_kv()
interfacen2 = app2.build()
manager.add_widget(interfacen2)
# add view 'interface3'
app3 = Interface3App()
app3.load_kv()
interfacen3 = app3.build()
manager.add_widget(interfacen3)
manager.transition = SlideTransition(direction="left")
return manager
In the screen manager login i import all the screens (ex: from interface1 import Interface1App)
In the second file, i put in self.list some data, and use it for that interface (filename : interface1.py):
from interface2 import Interface2App
class AllImage(Screen):
CONTAINER_PNG = os.path.join(AllImage_ROOT, 'images')
IMAGES_NAMES = [c[:-4] for c in os.listdir(CONTAINER_PNG)]
def __init__(self, **kwargs):
Screen.__init__(self, **kwargs)
for im in IMAGES_NAMES:
if IMAGES_NAMES != None :
toggleimage = ToggleWithImage(src=im+'.png')
toggleimage.bind(on_press= lambda a, im=im:self.onpress_addpage(self.listim, im))
self.layout.add_widget(toggleimage)
def change_screen(self, x, list):
self.manager.transition = SlideTransition(direction="left")
self.manager.current = 'interface2'
self.manager.get_screen('interface2')
self.manager.list1 = [1,2,3]
def backtologin(self):
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'login'
self.manager.get_screen('login')
class Interface1App(App):
'''The kivy App that runs the main root. All we do is build a AllImage
widget into the root.'''
def build(self):
screen = AllImage()
screen.name = 'interface1'
return screen
After that i want to use again the data collected in the 2nd interface (self.list) and use it in the 3rd Interface (filename: interace2.py):
from interface1 import AllImage #this isn't working
class Combinaison(Screen):
screen = ObjectProperty(None)
def __init__(self, **kwargs):
# self._previously_parsed_text = ''
super(Combinaison, self).__init__(**kwargs)
# self.list = list(self.manager.get_screen('interface1').list)
print(self.manager.list1) # The problem is here <===========
def backtointerface1(self):
self.manager.transition = SlideTransition(direction="right")
self.manager.current = 'interface1'
self.manager.get_screen('interface1')
class Interface2App(App):
'''The kivy App that runs the main root. All we do is build a Combinaison
widget into the root.'''
def build(self):
screen = Combinaison()
screen.name = 'interface2'
return screen
With this code i have this error : print(self.manager.list1)
AttributeError: 'NoneType' object has no attribute 'list1'
I think i didn't understand how i should use the self.manager.list1=[1, 2, 3]
I hope that i was clear, sorry for the long post.
Thank you for your time :)
You can use Screen.manager.get_screen(name).list = list(self.list)
A complete example:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
class Screen1(Screen):
list = [1,2,3]
def __init__(self,**kwargs):
super(Screen1,self).__init__(**kwargs)
self.switch_button = Button(text="goto 2")
self.switch_button.bind(on_release=self.switch)
self.add_widget(self.switch_button)
def switch(self,*args):
self.list = [4,5,6]
self.manager.get_screen("screen2").list = list(self.list)
self.manager.current = "screen2"
class Screen2(Screen):
def __init__(self,**kwargs):
super(Screen2,self).__init__(**kwargs)
self.switch_button = Button(text="goto 1")
self.switch_button.bind(on_release=self.switch)
self.add_widget(self.switch_button)
def switch(self,*args):
self.manager.current = "screen1"
def on_enter(self):
print self.list
class MainApp(App):
def build(self):
sc1 = Screen1(name="screen1")
sc2 = Screen2(name="screen2")
self.sm = ScreenManager()
self.sm.add_widget(sc1)
self.sm.add_widget(sc2)
return self.sm
MainApp().run()
You can also use the ScreenManager to store the list or lists.
self.manager.list1 = [1,2,3] # dont call this in __init__
self.manager.list2 = [4,5,6] # call it in on_enter instead
Those lists will be available from all screens after they are added to the manager. The on_enter method on the screen would be suitable for your example.

pyqt and weak/strong ref: how to proceed

[edit]
It seems I solved the problem... In fact, I now do that:
class Gameboard(QGraphicsScene):
def deletePawn(self, num):
pawnToDelete = self.pawns.pop(num)
pawnToDelete.delete()
class Pawn(QGraphicsItem):
def delete(self):
child.prepareGemotryChange()
child.setParent(None)
#idem for each child
self.gameboard.removeItem(self)
self.gameboard = None
[/edit]
What is the good way to implement references in a pyqt QGraphicsScene?
I made a class Gameboard which inherits QGraphicsScene, and this gameboard contains a variable number of pawns (wich inherit QGraphicsPolygonItem)
Pawns can be created or deleted dynamically, creation is ok but deletion sometimes crash...
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtOpenGL
class Gameboard(QGraphicsScene):
def __init__(self):
super(Gameboard, self).__init__()
self.pawns = {}
self.currentPawn = None
def createSquares(self):
#create the polygons of the squares and affect their coordinates x,y
def createPawn(self):
pawn = Pawn(self)
num = len(self.pawns)
self.pawns[num] = pawn
self.addItem(self.pawns[num])
def deletePawn(self, num):
self.currentPawn = None
self.pawns[num].beforeDelete()
self.pawns[num].prepareGeometryChange()
self.removeItem(self.pawns[num])
del self.pawns[num]
def selectPawn(self, pawn):
#a pawn is selected, by click for example
self.currentPawn = pawn
def keyPressEvent(self, event):
ekey = event.key()
if ekey == Qt.Key_Delete and self.currentPawn != None:
num = self.currentPawn.number
self.deletePawn(num)
class Pawn(QGraphicsItem):
def __init__(self, gameboard):
super(Pawn, self).__init__()
self.gameboard = gameboard
self.number = 0
self.pos = (-1,-1)
self.name = ""
def create(self, x, y, num):
#create a QGraphicsPolygonItem, a QGraphixPixmapItem and a QGraphicsTextItem which are child of the QGraphicsItem Pawn, and set position
self.number = num
self.pos = (x,y)
self.gameboard.squares[(x,y)].occupiedBy = self
def move(self, newPos):
self.gameboard.squares[self.pos].occupiedBy = None
self.pos = newPos
self.gameboard.squares[self.pos].occupiedBy = None
def beforeDelete(self):
#a function I add trying to get rid of the crash
self.gameboard = None
self.graphicsPolygon.setParent = None
self.graphicsPix.setParent = None
self.text.setParent = None
def mousePressEvent(self, event):
super(Pawn, self).mousePressEvent(event)
if event.button() == 1:
self.gameboard.currentPawn = self
event.accept()
class Square(QGraphicsPolygonItem):
def __init__(self, gameboard):
self.coordinates = (x,y)
self.occupiedBy = None
What is the proper way to proceed, should I use deleteLater?
Or maybe something with the weakref lib?
Is it because of the variable gameboard in Pawn?

PyQt: Call a TrayMinimized application

I have an application wich is minimized to the tray (showing an icon) when the user close it. What I need to know is how can I call it back with a combination of keys, like Ctrl+Alt+Something. Actually I call it back when I double-click it, but it will be nice to do the same on a keystroke. Here is a portion of the code:
# -*- coding: utf-8 -*-
"""The user interface for our app"""
import os,sys
import ConfigParser
# Import Qt modules
from PyQt4 import QtCore,QtGui
# Import the compiled UI module
from octo import Ui_Form
CFG_PATH = "etc/config.list" #Config File Path
#config.list vars DEFAULT Values
ClipCount = 8
Static = ""
window = None
# Create a class for our main window
class Main(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
# This is always the same
self.ui=Ui_Form()
self.ui.setupUi(self)
# Window Icon
icon = QtGui.QIcon("SSaver.ico")
self.setWindowIcon(icon)
self.setWindowTitle("Octopy")
# Set the timer =)
self.timer = self.startTimer(1000) #self.killTimer(self.timer)
# Clipboard Counter
self.counter = 0
#Last trapped clipboard
self.LastClip = ""
self.tentacles = [""] * 8
self.cmd = []
self.cmd.append(self.ui.cmd_1)
self.cmd.append(self.ui.cmd_2)
self.cmd.append(self.ui.cmd_3)
self.cmd.append(self.ui.cmd_4)
self.cmd.append(self.ui.cmd_5)
self.cmd.append(self.ui.cmd_6)
self.cmd.append(self.ui.cmd_7)
self.cmd.append(self.ui.cmd_8)
## Events ##
def on_cmd_8_pressed(self): #Clear
for i in range(0,7):
self.tentacles[i] = ""
self.cmd[i].setText(self.tentacles[i])
def on_cmd_1_pressed(self):
t = self.ui.cmd_1.text()
self.setClp(t)
def on_cmd_2_pressed(self):
t = self.ui.cmd_2.text()
self.setClp(t)
def on_cmd_3_pressed(self):
t = self.ui.cmd_3.text()
self.setClp(t)
def on_cmd_4_pressed(self):
t = self.ui.cmd_4.text()
self.setClp(t)
def on_cmd_5_pressed(self):
t = self.ui.cmd_5.text()
self.setClp(t)
def on_cmd_6_pressed(self):
t = self.ui.cmd_6.text()
self.setClp(t)
def on_cmd_7_pressed(self):
t = self.ui.cmd_7.text()
self.setClp(t)
def hideEvent(self,event): # Capture close and minimize events
pass
def keyPressEvent(self,ev):
if ev.key() == 16777216:
self.hide()
def showEvent(self,ev):
self.fillClp()
def timerEvent(self,ev):
c = self.getClp()
if c:
#print c, self.counter
self.tentacles[self.counter] = c
if self.counter < 7:
self.counter += 1
else:
self.counter = 0
self.fillClp()
## Functions ##
def fillClp(self):
for i in range(0,7):
self.cmd[i].setText(self.tentacles[i])
def getClp(self):
clp = QtGui.QApplication.clipboard()
c = clp.text()
if self.LastClip != c:
self.LastClip = c
return c
else:
return None
def setClp(self, t):
clp = QtGui.QApplication.clipboard()
clp.setText(t)
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, icon, parent=None):
QtGui.QSystemTrayIcon.__init__(self, icon, parent)
menu = QtGui.QMenu(parent)
# Actions
self.action_quit = QtGui.QAction("Quit", self)
self.action_about = QtGui.QAction("About Octopy", self)
# Add actions to menu
menu.addAction(self.action_about)
menu.addSeparator()
menu.addAction(self.action_quit)
# Connect menu with signals
self.connect(self.action_about, QtCore.SIGNAL("triggered()"), self.about)
self.connect(self.action_quit, QtCore.SIGNAL("triggered()"), self.quit)
# Other signals
traySignal = "activated(QSystemTrayIcon::ActivationReason)"
QtCore.QObject.connect(self, QtCore.SIGNAL(traySignal), self.icon_activated)
# Create Menu
self.setContextMenu(menu)
def quit(self):
w = QtGui.QWidget()
reply = QtGui.QMessageBox.question(w, 'Confirm Action',"Are you sure to quit?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
if reply == QtGui.QMessageBox.Yes:
QtGui.QApplication.quit()
def about(self):
w = QtGui.QWidget()
QtGui.QMessageBox.information(w, 'About', "Octopy Multi-Clipboard Manager\n Developed by mRt.")
def icon_activated(self, reason):
if reason == QtGui.QSystemTrayIcon.DoubleClick:
window.show()
else:
print "otro"
def main():
# Again, this is boilerplate, it's going to be the same on
# almost every app you write
app = QtGui.QApplication(sys.argv)
# TrayIcon
w = QtGui.QWidget()
icon = QtGui.QIcon("SSaver.ico")
trayIcon = SystemTrayIcon(icon, w)
trayIcon.show()
trayIcon.setToolTip("Octopy Multi-Clipboard Manager")
# Main Window
global window
window=Main()
window.show()
window.setWindowTitle("Octopy")
app.setQuitOnLastWindowClosed(0)
sys.exit(app.exec_())
def readIni():
cfg = ConfigParser.ConfigParser()
cfg.read(CFG_PATH)
ClipCount = int(cfg.get("Other","ClipCount"))
Static = cfg.get("Other","Static")
clip = [""] * int(ClipCount+1)
if __name__ == "__main__":
readIni()
main()
The complete program is hosted on google: http://code.google.com/p/octopys/downloads/list
For a keystroke to be handled by your application when it does not have keyboard focus, you need to install a global shortcut. Qt doesn't support this, but Qxt, a Qt extension library, does. See
http://doc.libqxt.org/0.5.0/classQxtGlobalShortcut.html. I don't know if PyQt bindings exist for Qxt.

Categories

Resources