I am using PyQt to create a GUI and need to create a periodic table made of buttons. Bellow is part of the code. Each button will require the following code in the method mainLayout(self).
class App(QMainWindow):
def __init___(self):
...
def mainLayout(self):
Element1 = QPushButton('shortname', self)
Element1.setToolTip('longname')
Element1.setCheckable(True)
Element1.resize(50, 50)
Element1.move(x, y)
Element1.clicked.connect(self.Element1_click)
This is a lot of repetitive code for one button when there will be 118 buttons. I made a GUI in the past which had this same problem and I remember I solved the issue with creating another class which I passed the argument for the unique attributes of each button.
I had something like this in mind where LayoutElm is a class.
LayoutElm(Element1 ,'shortname', 'longname', x, y, Element1_click)
Any ideas would be greatly appreciated.
You just have to create a function that creates the item:
class App(QMainWindow):
def __init___(self):
...
def mainLayout(self):
createLayoutElm('shortname', 'longname', (x, y), self.Element1_click)
createLayoutElm('shortname1', 'longname1', (100, 100), self.Element1_click2)
...
def createLayoutElm(self, name, tooltip, pos, callback):
btn = QPushButton(name, self)
btn.setToolTip(tooltip)
btn.setCheckable(True)
btn.resize(50, 50)
btn.move(*pos)
btn.clicked.connect(callback)
Related
#This class is to be used with other classes of widgets, not with the class of kivy.app.
class TempatureFloatLayout(FloatLayout):
tempature = NumericProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
Clock.schedule_interval(self.update, 1)
self.btn = Button()
self.btn.bind(on_press=self.do_something)
self.add_widget(self.btn)
def do_something(self, self_button):
pass
def update(self, dt):
self.btn.size = self.size # I can only resize and reposition the button here.
self.btn.pos = self.pos # pos and size are assigned with the pos and size
# values of the widget used
... the other codes
class TempatureFloatLayout(FloatLayout) can be used successfully in other classes. The code works correctly as it is. But, When every update, the position and size of the button is to be resized and repositioned. This doesn't feel right to me. How to bind a widget that is used and a button that is used in a different class. Where did I do wrong or is this usage correct?
I have a QGraphicsScene with many QGraphicsItem. Some items have buttons that clear and repaint the scene.
The problem is that the clear() method deletes the QButton (and its
associated data structures) in the middle of a method call that uses
those very data structures. Then, immediately after clear() returns,
the calling method tries to access the now-deleted data (because it
wasn't expecting to be deleted in the middle of its routine), and bang
-- a crash. From here.
I found the solution for C ++ here, however I am using PySide and could not use the same solution for python.
Follow my code:
class GraphicsComponentButtonItem(QtGui.QGraphicsItem):
def __init__(self, x, y, update_out):
super(GraphicsComponentButtonItem, self).__init__()
self.x = x
self.y = y
self.update_out = update_out
self.setPos(x, y)
self.createButton()
self.proxy = QtGui.QGraphicsProxyWidget(self)
self.proxy.setWidget(self.button)
def boundingRect(self):
return QtCore.QRectF(self.x, self.y, self.button.width(), self.button.height())
def paint(self, painter, option, widget):
# Paint same stuffs
def createButton(self):
self.button = QtGui.QPushButton()
self.button.setText('Clear')
self.button.clicked.connect(self.action_press)
def action_press(self):
# Run some things
self.update_out()
class QGraphicsViewButtons(QtGui.QGraphicsView):
def __init__(self, scene, parent=None):
QtGui.QGraphicsView.__init__(self, parent)
self.scene = scene
# It's called outside
def updateScene(self):
self.scene.clear()
self.scene.addItem(GraphicsComponentButtonItem(0, 0, self.updateScene))
self.scene.addItem(GraphicsComponentButtonItem(0, 50, self.updateScene))
self.scene.addItem(GraphicsComponentButtonItem(0, 100, self.updateScene))
the conversion of the following C++ code:
QObject::connect(button, SIGNAL(clicked()), scene, SLOT(clear()), Qt::QueuedConnection);
to python is:
self.button.clicked.connect(self.scene().clear, QtCore.Qt.QueuedConnection)
Hi I'm new to Qt and pyside. I'm trying to get the coordinates of mouse in a QGraphicsView instance. I tried to reimplement my mouseReleaseEvent but wondering how would I actually use this reimplemented function.
In MainWindow class:
self.tScn = QtGui.QGraphicsScene()
self.graphicsView_2 = QtGui.QGraphicsView(self.centralwidget, self.tScn)
In MainConsumer class(derived from MainWindow:
def pointSelection(self):
pos = self.tScn.mouseReleaseEvent(QMouseEvent)
print(pos)
def mouseReleaseEvent(self, QMouseEvent):
pos = QMouseEvent.lastScenePos()
print(pos)
return pos
python gives me this warning:
AttributeError: 'PySide.QtGui.QMouseEvent' object has no attribute 'lastScenePos'
I tried couple of different orders and structures but nothing worked and now I am really confused by the relationship between PySide.QtGui.QGraphicsScene.mouseReleaseEvent(event), PySide.QtGui.QGraphicsSceneMouseEvent.lastScenePos(), class PySide.QtGui.QGraphicsSceneMouseEvent([type=None]) and QtCore.QEvent.GraphicsSceneMouseRelease could somebody help me?
Thanks!
Create a class that inherits from QGraphicsScene and has a signal like this
class MyGraphicsScene(QtGui.QGraphicsScene):
signalMousePos = QtCore.pyqtSignal(QtCore.QPointF)
def __init__(self, parent):
super(MyGraphicsScene, self).__init__(parent)
and then override the mouseRelease event in this new class
def mouseReleaseEvent(QGraphicsSceneMouseEvent):
pos = QGrapihcsSceneMouseEvent.lastScenePos()
self.signalMousePos.emit(pos)
Then in your MainConsumer class replace
self.tScn = QtGui.QGraphicsScene()
with
self.tScn = MyQGraphicsScene()
self.tScn.signalMousePos.connect(self.pointSelection)
the pointSelection becomes
def pointSelection(self, pos)
#Whatever you want to do with the position coordinates
and mouseReleaseEvent in MainConsumer is no longer necessary
I'm trying to figure out how to bind a button that's been laid out using Kivy language to a function. I've seen plenty of answers when laying out buttons in Python language. But what about once everything is in place and you're now referencing via a custom class that inherits from Button?
On press, the code below throws the error TypeError: show() takes 1 positional argument but 2 were given and crashes the program.
class TimerButton(ButtonBehavior, Image):
timer_container = ObjectProperty(None)
client_scoreboard = ObjectProperty(None)
def __init__(self, **kwargs):
super(TimerButton, self).__init__(**kwargs)
self.bind(on_press=self.show)
self.bind(on_release=self.changeImage)
def show(self):
print('hi there')
self.source = 'assets/mainViewTimerButtonPressed.png'
import kivy.animation as Animate
anim = Animate.Animation(
x=self.client_scoreboard.right - self.timer_container.width,
y=self.timer_container.y,
duration=0.25)
anim.start(self.timer_container)
self.unbind(on_press=self.show)
self.bind(on_press=self.hide)
def changeImage(self):
self.source = 'assets/mainViewTimerButton.png'
def hide(self):
import kivy.animation as Animate
anim = Animate.Animation(
x=self.client_scoreboard.width,
y=self.timer_container.y,
duration=0.25)
anim.start(self.timer_container)
self.unbind(on_press=self.hide)
self.bind(on_press=self.show)
The kivy code that calls the function you set in .bind() is passing an argument which your function isn't prepared for. It's been a while since I last used kivy, so I can't be sure, but I think the event details are passed to the function.
As such, your definitions for event handlers should look like this:
def show(self, event):
...
def hide(self, event):
...
If you're curious, you could print(event) within those functions, to see what's being sent in.
The answer is to include the class name, in this case TimerButton, in the function definitions. This is a concept I don't completely understand since the function is defined within the scope of the TimerButton class. But hey, it works.
class TimerButton(ButtonBehavior, Image):
timer_container = ObjectProperty(None)
client_scoreboard = ObjectProperty(None)
def __init__(self, **kwargs):
super(TimerButton, self).__init__(**kwargs)
self.bind(on_press=self.show)
self.bind(on_release=self.changeImage)
def show(self):
print('hi there')
self.source = 'assets/mainViewTimerButtonPressed.png'
import kivy.animation as Animate
anim = Animate.Animation(
x=self.client_scoreboard.right - self.timer_container.width,
y=self.timer_container.y,
duration=0.25)
anim.start(self.timer_container)
self.bind(on_press=self.hide)
def changeImage(self):
self.source = 'assets/mainViewTimerButton.png'
def hide(self):
import kivy.animation as Animate
anim = Animate.Animation(
x=self.client_scoreboard.width,
y=self.timer_container.y,
duration=0.25)
anim.start(self.timer_container)
self.bind(on_press=self.show)
I want a certain function callable on a class. Something similar to:
class foo():
def __init__(self):
self.img = pygame.Surface((20, 20))
def magicfunction(self):
return self.img
bar = foo()
screen = pygame.display.set_mode((200, 200))
screen.blit(bar)
Which magic-function do I have to use?
If I understand you correctly, you want to create a class of your own, which is also a surface. That sounds exactly like inheritance! Try making foo a child of pygame.Surface:
class foo(pygame.Surface):
def __init__(self):
pygame.Surface.__init__(self, (20, 20))
more_data = "You should be able to extend this class freely"