Moving label PyQt - python

I have a class like the following representing a game Card. There are more cards displayed on the table but I'd like that when one is clicked it goes at the center of the table. Now, there could already be another card at the center of the table (let's assume the center is at coordinates 100x, 100y) so if this is the case I'd like to position the new card next to it, say, at 200x, 100y but how do I tell if there's something already at 100, 100?
from PyQt4 import QtGui, QtCore
class CardLabel(QtGui.QLabel):
def __init__(self, *args, **kwargs):
QtGui.QLabel.__init__(self, *args, **kwargs)
def mouseReleaseEvent(self, ev):
print 'clicked'
self.emit(QtCore.SIGNAL('clicked()'))
self.move(100, 100)
I cannot find any QLabel attribute (not even in its inherited parents) nor method that returns the coordinates of a label. If I could I would maybe record the coordinates of all widgets in a global dictionary and loop over its items every time I have to move a card (would that be the best way or is there something more efficient?).

QLabel inherits from QWidget so the x(), y(), pos() and other similar functions are all available to it. Also you can have a look to the Window Geometry documentation that can help you. When you put a card at the center of the table you can update some dictionary or similar with the relevant information. If you want to put a new card at the center just read the dictionary and do things accordingly to its content.

Related

Including a docstring in another docstring

Problem: I want to use one docstring in another docstring.
Suppose I have the following snippet:
def window(dimensions: tuple):
'''
Function to create an app window and return it
PARAMETERS
----------
dimensions : tuple
The width and height of the window to create
RETURNS
-------
display.Window
Class to implement a screen # Make this equal to Window.__doc__
'''
class Window:
'''
Class to implement a screen
'''
def __init__(self, dimensions: tuple):
pass
return Window(dimensions)
I want to automatically set the docstring for window to include the docstring for Window
I read that you can set the docstring manually, like so:
window.__doc__ = "".join((window.__doc__, Window.__doc__))
But it is only executed when the function is called.
Also, I could use decorators, but is there a simpler intuitive way to do this?
Bonus: Is there a way to decide exactly where in the docstring I can include another?
EDIT: So, it looks like there is a duplicate suggestion to this question, but since I specifically asked without decorators, that does make my question somewhat different. Also, my use of nested class in window means that any attempt to change __doc__:
inside of window: will not occur until function is called.
outside of window: will not run as Window is nested.
So this rules both these methods out, as things stand.
But the answer of course has to be one of these. So the answer is a duplicate, not the question. :P
Therefore, I had to restructure my code. See below.
Thanks to #aparpara, I found that answer (which didn't show up when I searched it online), and it made me realise there is (possibly?) no solution to my specific question.
Therefore, I had to remove the nested class to be able to access it outside the function.
Here is the final version.
# module display_module.py
class Window:
'''
Class to implement pygame's screen
'''
def __init__(self, dimensions: tuple):
pass
def window(dimensions: tuple):
'''
Function to create an app window and return it
PARAMETERS
----------
dimensions : tuple
The width and height of the window to create
RETURNS
-------
display.Window
{0}
'''
return Window(dimensions)
window.__doc__ = window.__doc__.format(Window.__doc__.strip())
Still open to any answers to the old question!

How to animate a button on kivy when the cursor is over it?

I'm kinda new to Kivy and I was looking for a way to animate the button when the cursor is over it.
I've tried to manage a way to get the mouse position and compare it with the button coordinates but no success at all.
This question has already been (mostly) answered at this post.There is a very nice example of this here by Olivier POYEN under LGPL license. Basically he has defined a class called HoverBehavior that you should inherit from to make a new class, e.g. HoverButton or HoverLabel (as his example shows). Then you have access to the on_enter and on_leave functions, which you can use to change the button's image, or change a label's text color, or whatever you need.
To answer your exact question, I would seek to understand the HoverBehavior class, then copy/paste it from the source above, then make a new class like so:
class HoverButton(Button, HoverBehavior):
def on_enter(self, *args):
self.background_normal = "some_image1.png" # Change the button's image when entered
def on_leave(self, *args):
self.background_normal = "some_other_image.png" # Change image when leaving
or you could use the kv language which looks even cleaner:
<HoverButton>:
background_normal: "some_image1.png" if self.hovered else "some_other_image.png"
just make sure you include a base class for the HoverButton in your python script if you use the 2nd option:
class HoverButton(Button, HoverBehavior):
pass

Getter/setter but for nested attributes?

Suppose I have two classes. The simple Square class:
class Square:
def __init__(self, side):
self.side = side
And the slightly more complex MyClass class:
class MyClass:
def __init__(self, square=None):
if square is None:
self.square = Square()
else:
self.square = square
self.rounded_side = round(self.square.side)
I instantiate a MyClass object like so:
myObj = MyClass()
In this situation, how can one achieve the following behavior?
Changing myObj.rounded_side to X, automatically changes myObj.square.side also to X.
Changing myObj.square.side to X, automatically changes myObj.rounded_side to round(X).
If possible, in a way that doesn't require any modifications to the Square class (this is a simplified version of the problem I'm currently facing; in the original version, I don't have access to the code for Square).
What I tried so far:
My first attempt was to transform rounded_side into a property. That makes it possible to obtain behavior 1. However, I fail to see how I can transform square also into a property, in a way that makes it possible to obtain behavior 2.
I also thought about making MyClass inherit from Square, so that both attributes are in the same depth, but then I'd lose some the desired structure of my class (I rather have the user access myObj.square.side, than myObj.side)
If someone is interested, the actual problem I'm facing:
I'm writing a game in pygame, and my Player class has an attribute for its position, which is an array with two floats (2D position). This is used for determining where the player is, and for deciding how to update it's position in the next update step of the game's physics.
However, I also want to have a Rect attribute in the Player class (which holds the information about a rectangle around the player's image), to be used when displaying the player in the screen, and when inferring collisions. The Rect class uses integers to store the position of the rectangle (pixel coordinates).
So as to be able to store the position information of the player in a float, but also use the Rect class for convenience, I thought about having this dependency between them, where changing one alters also the other accordingly.
As you've said, make rounded_side a property, but have it access the value in self.square for both getting and setting.
#property
def rounded_side(self):
return self.square.side
#rounded_side.setter
def rounded_side(self, side):
self.square.side = side
Now, setting rounded_side will use the setter which sets the value in square; setting the value on square directly will mean that it would be looked up from there by the property getter.

Add a QGraphicsView to a QGraphicsWidget

I am trying to display a QGraphicsView inside a QGraphicsWidget, but I can't seem to get it to work.
This is what I want to achieve, where the QGraphicsWidgets are all added to a QGraphicsScene, and each widget has their own QGraphicsScene and QGraphicsView.
The large box represents the main view, and the smaller boxes represent widgets, each with their own view and scenes.
My current implementation doesn't work, due to the following error:
TypeError: QGraphicsLinearLayout.addItem(QGraphicsLayoutItem):
argument 1 has unexpected type 'QGraphicsView'
My implemetation in a subclass of the QGraphicsWidget:
self.scene = QtGui.QGraphicsScene(self)
self.view = QtGui.QGraphicsView(self.scene)
self.view.setRenderHint(QtGui.QPainter.Antialiasing)
self.setLayout(QtGui.QGraphicsLinearLayout(Qt.Vertical))
self.layout().addItem(self.view)
I've tried to implement this with a QGraphicsLayoutItem, but I couldn't find anywhere to stick the QGraphicsView in.
Any help would be appreciated.
The function QGraphicsLinearLayout.addItem expects a QGraphicsWidget parameter and you are passing a normal QWidget (QGraphicsView).
You can use the class QGraphicsProxyWidget which is specially designed for wrapping QWidget into QGraphicsWidget.
I do not have Qt + Python on hands but I think it should look as follows:
proxy = parentView.addWidget(nestedView) # QWidget -> QGraphicsWidget
self.layout().addItem(proxy)

Recommend way to handle unit conversion

I'm making a GUI with pyqt4 and python. Right now I have a QLineEdit and QComboBox, where the QLineEdit displays the values and the QComboBox can be used to change units. I'm using signals and slots to handle real time unit/value feedback for the user but I'm having problems understanding how to programmatically work with the values as I need them all to be in standard units. Here's what I've got so far, the combo_box_line_edit_list is a list of list where I wrap the combo box and line list together
class UnitConverterSignaler(QtCore.QObject):
def __init__(self, combo_box_line_edit_list):
super(QtCore.QObject, self).__init__()
self.combo_box_line_edit_list = combo_box_line_edit_list
self.combo_box_list = [line_edit_combo_box[0] for line_edit_combo_box in combo_box_line_edit_list]
for combo_box, line_edit in self.combo_box_line_edit_list:
combo_box.currentIndexChanged['QString'].connect(line_edit.convert_units)
line_edit.store_unit_state(combo_box.currentText())
line_edit.standard_unit = combo_box.itemText(1)
def convert_to_standard(self):
for combo_box in self.combo_box_list:
combo_box.setCurrentIndex(0)
def convert_to_international(self):
for combo_box in self.combo_box_list:
combo_box.setCurrentIndex(1)
def toggle_unit_conversion(self, hold_line_values_steady):
for combo_box in self.combo_box_list:
if hold_line_values_steady:
combo_box.do_not_convert_units_on_change()
else:
combo_box.convert_units_on_change()
def convert_units_on_change(self):
"""
Changes the value of the line edit each time the combo box is changed
"""
for combo_box, line_edit in self.combo_box_line_edit_list:
combo_box.currentIndexChanged['QString'].connect(line_edit.convert_units)
combo_box.currentIndexChanged['QString'].disconnect(line_edit.store_unit_state)
def do_not_convert_units_on_change(self):
"""
Holds the line edit value constant in spite of combo box changes
"""
for combo_box, line_edit in self.combo_box_line_edit_list:
combo_box.currentIndexChanged['QString'].disconnect(line_edit.convert_units)
combo_box.currentIndexChanged['QString'].connect(line_edit.store_unit_state)
Instantiated & used in another class
self.lockCellCheckBox.toggled.connect(self.unit_converter_signaler.toggle_unit_conversion)
self.internationalPushButton.clicked.connect(self.unit_converter_signaler.convert_to_international)
self.standardPushButton.clicked.connect(self.unit_converter_signaler.convert_to_standard)
I've also monkey patched the QLineEdit instead of subclassing so I can make quick changes with QtDesigner.
# monkey patch slot onto line_edit
def convert_units(line_edit, end_unit):
converted_unit_value = line_edit.unit_registry.convert(float(line_edit.text()), line_edit.stored_unit_state, str(end_unit))
line_edit.setText(str(converted_unit_value))
line_edit.stored_unit_state = str(end_unit)
# monkey patch slot onto line_edit
def store_unit_state(line_edit, unit):
line_edit.stored_unit_state = str(unit)
Would the most generalized way to get the standard units out in my main program be the creation of a signal for each combo box/line edit in the UnitConverter?
From what I understood so far: you have many combo-box/line-edit pairs and the entered values should always be converted to standard units (e.g. displayed on a third QLabel or whatever).
Would the most generalized way to get the standard units out in my main program be the creation of a signal for each combo box/line edit in the UnitConverter?
No, you don't have to. A slot in python (or especially in pyqt) can be any callable object. A callable object is an object with method __call__(self) implemented.
Therefore I would suggest you to create a class which takes the related object(s) as parameter(s) in the contructor and changes them in __call__(self). Something like this:
class ConverterSignal:
def __init__(whatever_you_want_to_refer_to):
self.whatever_you_want_to_refer_to = whatever_you_want_to_refer_to
def __call(self)__:
""" Here you can refer to whatever_you_want_to_refer_to and do whatever you want with it """
The connection is done as following (for the combo box as an example):
self.connect(combo_box, QtCore.SIGNAL('activated(int)'), ConverterSignal(whatever_you_want_to_refer_to))
Here an instance of the class ConverterSignal is created and will be called if the corresponding signal is emitted.

Categories

Resources