Results 1 to 4 of 4

Thread: How to show two states of a rectangle in PyQt/PySide2

  1. #1
    Join Date
    Oct 2019
    Posts
    12
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Windows

    Default How to show two states of a rectangle in PyQt/PySide2

    I have what I thought was a simple task. I have an alert button (QGraphicsRectItem) in a graphics scene which has 2 rectangle children, each with its own, same text. I create the alert with rect 1 with a darkGray brush, a white border and white text. Rect 2 is supposed to have a yellow fill brush and black text. When I press a button I hide one set and show the other.

    The problem is that the yellow rectangle doesn't show up, but its text does! What am I doing wrong?

    Qt Code:
    1. import sys
    2. from PyQt5 import QtGui, QtWidgets
    3. from PyQt5.QtCore import *
    4. from PyQt5.QtGui import QPainter, QColor
    5. #from PyQt5.QtCore import QCoreApplication
    6. from pynput import keyboard
    7.  
    8.  
    9. class Geo:
    10. def __init__(self, x, y, w, h):
    11. self.x = x
    12. self.y = y
    13. self.w = w
    14. self.h = h
    15.  
    16.  
    17. class Alert(QtWidgets.QGraphicsRectItem):
    18. def __init__(self, key_name, key_char, geo, parent=None, highlight_color=QColor(255, 255, 0, 200)):
    19. super(Alert, self).__init__(parent)
    20. self.key_name = key_name
    21. self.geo = geo
    22.  
    23. rect = QRectF(0, 0, geo.w, geo.h)
    24. normal = QtWidgets.QGraphicsRectItem(rect, self)
    25. normal.setBrush(Qt.darkGray)
    26. normal.setPen(Qt.white)
    27. normal_txt = QtWidgets.QGraphicsSimpleTextItem(key_char, normal)
    28.  
    29. brush = QtGui.QBrush(Qt.white)
    30. normal.setBrush(brush)
    31. self.normal = normal
    32.  
    33. #self.highlighted = QtWidgets.QGraphicsRectItem(normal)
    34. self.highlighted = QtWidgets.QGraphicsRectItem(self)
    35. brush2 = QtGui.QBrush(highlight_color)
    36. self.highlighted.setBrush(brush2)
    37. #self.highlighted.setBrush(highlight_color)
    38. #self.highlighted.setBrush(brush)
    39. txt = QtWidgets.QGraphicsTextItem(key_char, self.highlighted)
    40. txt.setX(geo.w/2)
    41. #self.highlighted.hide()
    42.  
    43. def highlight(self, on=False):
    44. if on:
    45. self.highlighted.show()
    46. self.normal.hide()
    47. else:
    48. self.highlighted.hide()
    49. self.normal.show()
    50.  
    51.  
    52. class MainWindow(QtWidgets.QMainWindow):
    53. def __init__(self, parent=None):
    54. super(MainWindow, self).__init__(parent)
    55. self.scene = QtWidgets.QGraphicsScene(self)
    56. self.scene.setItemIndexMethod(QtWidgets.QGraphicsScene.NoIndex)
    57.  
    58. geo = Geo(10, 10, 50, 50)
    59. self.buzz = Alert("Buzz", "Buzz", geo)
    60. self.scene.addItem(self.buzz)
    61. self.buzz.setPos(QPointF(130, 120))
    62.  
    63. self.create_central_widget()
    64.  
    65. self.listener = keyboard.Listener(
    66. on_press=self.on_press,
    67. on_release=self.on_release)
    68. self.listener.start()
    69.  
    70. def create_layout(self):
    71. self.layout = QtWidgets.QGraphicsLinearLayout()
    72. self.widget = QtWidgets.QGraphicsWidget()
    73. self.widget.setLayout(self.layout)
    74. self.scene.addItem(self.widget)
    75.  
    76. width = self.keyboard_width
    77. height = self.keyboard_height
    78. self.setMinimumSize(width, height)
    79. self.scene.setSceneRect(0, 0, width, height)
    80.  
    81. def create_central_widget(self):
    82. self.view = QtWidgets.QGraphicsView(self.scene)
    83. self.view.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing)
    84. self.view.setBackgroundBrush((QColor("bisque")))
    85. self.setCentralWidget(self.view)
    86. self.view.scale(3, 3)
    87.  
    88. def on_press(self, key):
    89. self.buzz.highlight(True)
    90.  
    91. def on_release(self, key):
    92. self.buzz.highlight(False)
    93.  
    94.  
    95. def main():
    96. app = QtWidgets.QApplication(sys.argv)
    97. w = MainWindow()
    98. w.show()
    99. ret = app.exec_()
    100. sys.exit(ret)
    101.  
    102. if __name__ == "__main__":
    103. main()
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to show two states of a rectangle in PyQt/PySide2

    I don't see where you are setting the rect for self.highlighted (which you do set for normal / self.normal). So self.highlighted has zero size.

    But this hide / show mechanism seems pretty complicated when all you want to do in actuality is to change the color of a rectangle. Why not simply set a new brush on a -single- QGraphicsRectItem instead of flip / flopping two of them?
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. The following user says thank you to d_stranz for this useful post:

    illuzioner1 (10th March 2020)

  4. #3
    Join Date
    Oct 2019
    Posts
    12
    Thanks
    1
    Thanked 1 Time in 1 Post
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to show two states of a rectangle in PyQt/PySide2

    You're right, that was the problem. In my shifting things around I lost the 'rect' in the second rectangle. Good idea on the brush. This is a simplified version of what I'm doing so I'll have to see if that works (as pixmaps are a possibility).

    Thank you for the help!

  5. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: How to show two states of a rectangle in PyQt/PySide2

    (as pixmaps are a possibility)
    Same principle as a brush. In Qt, QPixmap instances are reference-counted, so there is no overhead associated with changing the pixmap for a QGraphicsPixmapItem. QGraphicsPixmapItem::setPixmap() takes a const reference to a QPixmap, which implies that the graphics item stores a local copy, but that's not necessarily the case. Even when setting a pixmap is pass-by-value, the reference counting means that no actual copy is made unless the target of the copy modifies the original pixmap (ie. copy-on-write semantics apply).
    Last edited by d_stranz; 10th March 2020 at 05:25.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Replies: 5
    Last Post: 20th February 2020, 21:28
  2. Pyqt: How to show a QFileDialog?
    By robgeek in forum Qt Programming
    Replies: 3
    Last Post: 10th October 2016, 09:35
  3. QtPen draw wrong border for Rectangle (PyQt)
    By Goodwin in forum Qt Programming
    Replies: 4
    Last Post: 17th October 2014, 16:53
  4. QtQuick Rectangle control what borders show?
    By ricardodovalle in forum Qt Quick
    Replies: 3
    Last Post: 27th May 2014, 17:39
  5. gif files don't show after compiling with py2exe (using PyQt)
    By illuminatedwax in forum Installation and Deployment
    Replies: 4
    Last Post: 31st January 2011, 05:13

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.