I want to draw a transparent-background rectangle in pyqt. The following code meets my need in Mac:
import sys
from PyQt4 import QtGui, QtCore, Qt
class ZoomWidget(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
#self.setAttribute(Qt.Qt.WA_NoSystemBackground)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.setStyleSheet("background-color:transparent;")
self.setGeometry(100,100,100,100)
self.show()
def paintEvent(self, e=None):
qp = QtGui.QPainter()
qp.begin(self)
qp.setPen( QtGui.QPen(QtCore.Qt.gray,3,QtCore.Qt.DashDotLine ) )
qp.drawRect(0,0,self.rect().width()-1, self.rect().height()-1)
qp.end()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
ex = ZoomWidget()
sys.exit(app.exec_())
However, when I used this code in Linux, it gave me a black-background rectangle. What should I do to give the transparent background to it? Thanks.
have you tried to set parent of ZoomWidget ?
...
def __init__(self, *args, **kwargs):
QtGui.QWidget.__init__(self, *args, **kwargs)
...
app = QtGui.QApplication(sys.argv)
dial = QtGui.QDialog()
ex = ZoomWidget(parent=dial)
dial.show()
...
Related
I want to move the QLabel with the mouse movement (not like Drag&drop, 'object' disappears while moving). Clicked - moved - released. I did it to some extent, but I ran into a problem. QLabel shrinks as I move it or even disappears (like shrinks to 0 width). How to fix it or what more correct approach to do it?
(self.label_pos is needed to keep the mouse position relative inside self.label)
Or its just monitor's refresh rate issue? But in photoshop's gradient editor, that little color stop isn't shrikns. It's choppy because of refresh rate, but always the same size.
This is what I want to see, recorded using a screen capture program. The same thing I see in Photoshop
This is what I see, recorded on my phone. The quality is poor, but the difference is clearly visible anyway.
This Photoshop is also captured on my phone, here the “object” remains the same size, as in the example made using screen capture
Here is code from eyllanesc's answer, 'object' still shrinks :(
self.label = QLabel(self)
self.label.move(100, 100)
self.label.mousePressEvent = self.mouse_on
self.label.mouseReleaseEvent = self.mouse_off
def mouse_on(self, event):
self.bool = True
self.label_pos = event.pos()
def mouse_off(self, event):
self.bool = False
def mouseMoveEvent(self, event):
if self.bool:
self.label.move(event.x()-self.label_pos.x(), event.y()-self.label_pos.y())
Instead of using a QLabel I recommend using QGraphicsRectItem with a QGraphicsView since it is specialized in this type of tasks:
from PyQt5 import QtCore, QtGui, QtWidgets
class Widget(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.setScene(QtWidgets.QGraphicsScene(self))
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
brush = QtWidgets.QApplication.palette().brush(QtGui.QPalette.Window)
self.setBackgroundBrush(brush)
rect_item = self.scene().addRect(
QtCore.QRectF(QtCore.QPointF(), QtCore.QSizeF(40, 80))
)
rect_item.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
rect_item.setBrush(QtGui.QBrush(QtGui.QColor("red")))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.setFixedSize(640, 480)
w.show()
sys.exit(app.exec_())
If you want to just scroll horizontally then overwrite the itemChange method of QGraphicsItem:
from PyQt5 import QtCore, QtGui, QtWidgets
class HorizontalItem(QtWidgets.QGraphicsRectItem):
def __init__(self, rect, parent=None):
super(HorizontalItem, self).__init__(rect, parent)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)
def itemChange(self, change, value):
if (
change == QtWidgets.QGraphicsItem.ItemPositionChange
and self.scene()
):
return QtCore.QPointF(value.x(), self.pos().y())
return super(HorizontalItem, self).itemChange(change, value)
class Widget(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.setScene(QtWidgets.QGraphicsScene(self))
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
brush = QtWidgets.QApplication.palette().brush(QtGui.QPalette.Window)
self.setBackgroundBrush(brush)
rect_item = HorizontalItem(
QtCore.QRectF(QtCore.QPointF(), QtCore.QSizeF(40, 80))
)
rect_item.setBrush(QtGui.QBrush(QtGui.QColor("red")))
self.scene().addItem(rect_item)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.setFixedSize(640, 480)
w.show()
sys.exit(app.exec_())
In the following code there is an example similar to what you want:
from PyQt5 import QtCore, QtGui, QtWidgets
class HorizontalItem(QtWidgets.QGraphicsRectItem):
def __init__(self, rect, parent=None):
super(HorizontalItem, self).__init__(rect, parent)
self.setFlag(QtWidgets.QGraphicsItem.ItemIsMovable, True)
self.setFlag(QtWidgets.QGraphicsItem.ItemSendsGeometryChanges, True)
def itemChange(self, change, value):
if (
change == QtWidgets.QGraphicsItem.ItemPositionChange
and self.scene()
):
return QtCore.QPointF(value.x(), self.pos().y())
return super(HorizontalItem, self).itemChange(change, value)
class Widget(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.setScene(QtWidgets.QGraphicsScene(self))
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
brush = QtWidgets.QApplication.palette().brush(QtGui.QPalette.Window)
self.setBackgroundBrush(brush)
self.setFixedSize(640, 480)
size = self.mapToScene(self.viewport().rect()).boundingRect().size()
r = QtCore.QRectF(QtCore.QPointF(), size)
self.setSceneRect(r)
rect = QtCore.QRectF(
QtCore.QPointF(), QtCore.QSizeF(0.8 * r.width(), 80)
)
rect.moveCenter(r.center())
rect_item = self.scene().addRect(rect)
rect_item.setBrush(QtGui.QBrush(QtGui.QColor("salmon")))
item = HorizontalItem(
QtCore.QRectF(
rect.bottomLeft() + QtCore.QPointF(0, 20), QtCore.QSizeF(20, 40)
)
)
item.setBrush(QtGui.QBrush(QtGui.QColor("red")))
self.scene().addItem(item)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
How can I append a painted rectangle to a QIcon. The final returned result has to be a qicon because I'm using this on a control which expects a qicon.
Before:
After:
import os, sys
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.resize(600,400)
self.btn = QtGui.QPushButton()
self.btn.setFixedSize(128,128)
icon = QtGui.QIcon('thumb.jpg')
self.btn.setIconSize(icon.availableSizes()[0])
self.btn.setIcon(icon)
lay = QtGui.QVBoxLayout()
lay.addWidget(self.btn)
self.setLayout(lay)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You have to read the image as QPixmap, use QPainter to modify the QPixmap by adding the rectangle and finally use the QPixmap to create the QIcon
import sys
from PySide import QtCore, QtGui
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
self.resize(600,400)
lay = QtGui.QHBoxLayout(self)
pixmap = QtGui.QPixmap('thumb.jpg')
painter = QtGui.QPainter(pixmap)
painter.fillRect(QtCore.QRect(20, 20, 40, 40), QtGui.QColor("red"))
painter.end()
for icon in (QtGui.QIcon('thumb.jpg'), QtGui.QIcon(pixmap)):
btn = QtGui.QPushButton()
btn.setFixedSize(128,128)
btn.setIconSize(icon.availableSizes()[0])
btn.setIcon(icon)
lay.addWidget(btn)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Example code I am using:
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.open_about = False
self.openAction = QtWidgets.QAction('About', self)
self.openAction.triggered.connect(self.aboutDialog)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.calendar = QtWidgets.QCalendarWidget(self)
self.setCentralWidget(self.calendar)
def about_state_upd(self, value):
self.open_about = value
def aboutDialog(self):
self._about = AboutDialog(self)
self._about.exec_()
def hideEvent(self, hideEvent):
if self.open_about == True:
self._about.setVisible(False)
def showEvent(self, showEvent):
if self.open_about == True:
if self._about.isHidden() == True:
self._about.setModal(True)
self._about.setVisible(True)
class AboutDialog(QtWidgets.QDialog):
def __init__(self, parent):
super(AboutDialog, self).__init__(parent)
self.setMinimumSize(400, 350)
self.parent().about_state_upd(True)
def closeEvent(self, closeEvent):
self.parent().about_state_upd(False)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
sys.exit(app.exec_())
This code basically works, but seems very complicated. Is there a simpler / cleaner way to make it so that when the modal QDialog is open, if the QMainWindow is minimized, the QDialog also gets minimized too (and reverse when QMainWindow is restored)?
Code is running on KDE Neon (Kubuntu-based distro).
May be you can use this: http://korbinin.blogspot.fr/search/label/minimize%20button
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MainForm(QDialog):
def __init__(self, fn=None,parent=None):
super(MainForm, self).__init__(parent,\
flags=Qt.WindowMinimizeButtonHint|Qt.WindowMaximizeButtonHint)
Thanks to the people on the PyQt Mailing list, I managed to get a workaround for KDE. Instead of using exec_(), I am just using show() - then I use setDisabled() on QMainWindow to make dialog act in a modal fashion. Here is a (very quick and basic) example for anyone interested:
import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.openAction = QtWidgets.QAction('About', self)
self.openAction.triggered.connect(self.aboutDialog)
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.openAction)
self.calendar = QtWidgets.QCalendarWidget(self)
self.setCentralWidget(self.calendar)
def aboutDialog(self):
self._about = AboutDialog(self)
self.setDisabled (True)
self._about.show()
def enableWidgets(self):
self.setDisabled(False)
class AboutDialog(QtWidgets.QDialog):
def __init__(self, parent):
super(AboutDialog, self).__init__(parent)
self.setMinimumSize(400, 350)
def closeEvent(self, parent):
self.parent().enableWidgets()
def changeEvent(self, event):
if event.type() == QtCore.QEvent.WindowStateChange:
if self.windowState() & QtCore.Qt.WindowMinimized:
self.parent().showMinimized()
else:
self.parent().showMaximized()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app_window = MainWindow()
app_window.showMaximized()
sys.exit(app.exec_())
Link to PyQt Mailing List posts.
I have a button and two tablewidgets.Pressing the button does two different things depending on which one of the tablewidgets was activated before the push of the button.How can I get the right widget?
You could for example use the focusInEvent to store the activated widget and return it when pressing the button, something like this:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore
class MyTableWidget(QtGui.QTableWidget):
focusIn = QtCore.pyqtSignal(QtCore.QObject)
def __init__(self, parent=None):
super(MyTableWidget, self).__init__(parent)
def focusInEvent(self, event):
self.focusIn.emit(self)
return super(MyTableWidget, self).focusInEvent(event)
class MyWindow(QtGui.QWidget):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.lastFocusedTableWidget = None
self.tableWidgetFirst = MyTableWidget(self)
self.tableWidgetFirst.setObjectName("tableWidgetFirst")
self.tableWidgetFirst.focusIn.connect(self.on_tableWidget_focusIn)
self.tableWidgetSecond = MyTableWidget(self)
self.tableWidgetSecond.setObjectName("tableWidgetSecond")
self.tableWidgetSecond.focusIn.connect(self.on_tableWidget_focusIn)
self.pushButtonLastFocused = QtGui.QPushButton(self)
self.pushButtonLastFocused.setText("Print the last focused QTableWidget!")
self.pushButtonLastFocused.clicked.connect(self.on_pushButtonLastFocused_clicked)
self.layoutVertical = QtGui.QVBoxLayout(self)
self.layoutVertical.addWidget(self.tableWidgetFirst)
self.layoutVertical.addWidget(self.tableWidgetSecond)
self.layoutVertical.addWidget(self.pushButtonLastFocused)
#QtCore.pyqtSlot(QtCore.QObject)
def on_tableWidget_focusIn(self, obj):
self.lastFocusedTableWidget = obj
#QtCore.pyqtSlot()
def on_pushButtonLastFocused_clicked(self):
print self.lastFocusedTableWidget.objectName()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.resize(333, 111)
main.show()
sys.exit(app.exec_())
Im trying to do simple audio player, but I want use a image(icon) as a pushbutton.
You can subclass QAbstractButton and make a button of your own. Here is a basic simple example:
import sys
from PyQt4.QtGui import *
class PicButton(QAbstractButton):
def __init__(self, pixmap, parent=None):
super(PicButton, self).__init__(parent)
self.pixmap = pixmap
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPixmap(event.rect(), self.pixmap)
def sizeHint(self):
return self.pixmap.size()
app = QApplication(sys.argv)
window = QWidget()
layout = QHBoxLayout(window)
button = PicButton(QPixmap("image.png"))
layout.addWidget(button)
window.show()
sys.exit(app.exec_())
That's not a super easy way, but it gives you a lot of control. You can add second pixmap and draw it only when the mouse pointer is hover over button. You can change current stretching behavior to the centering one. You can make it to have not a rectangular shape and so on...
Button that changes images on mouse hover and when pressed:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class PicButton(QAbstractButton):
def __init__(self, pixmap, pixmap_hover, pixmap_pressed, parent=None):
super(PicButton, self).__init__(parent)
self.pixmap = pixmap
self.pixmap_hover = pixmap_hover
self.pixmap_pressed = pixmap_pressed
self.pressed.connect(self.update)
self.released.connect(self.update)
def paintEvent(self, event):
pix = self.pixmap_hover if self.underMouse() else self.pixmap
if self.isDown():
pix = self.pixmap_pressed
painter = QPainter(self)
painter.drawPixmap(event.rect(), pix)
def enterEvent(self, event):
self.update()
def leaveEvent(self, event):
self.update()
def sizeHint(self):
return QSize(200, 200)
You can use QToolButton with set autoraise property true and there you can set your image also.
I've seen that a lot of people have this problem and decided to write a proper example on how to fix it. You can find it here: An example on how to make QLabel clickable
The solution in my post solves the problem by extending QLabel so that it emits the clicked() signal.
The extended QLabel looks something like this:
class ExtendedQLabel(QLabel):
def __init__(self, parent):
QLabel.__init__(self, parent)
def mouseReleaseEvent(self, ev):
self.emit(SIGNAL('clicked()'))
I hope this helps!
Something like this, maybe?
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
app = QApplication(sys.argv)
widget = QWidget()
layout = QHBoxLayout()
widget.setLayout(layout)
button = QPushButton()
layout.addWidget(button)
icon = QIcon("image.png")
button.setIcon(icon)
widget.show()
app.exec_()
Another option is to use stylesheets. Something like:
from PyQt4 import QtCore, QtGui
import os
...
path = os.getcwd()
self.myButton.setStyleSheet("background-image: url(" + path + "/myImage.png);")
If you want use an image instead of a QPushButton in menubar or in toolbar, you can do it via QAction. Working example:
from PyQt5 import QtWidgets, QtGui, QtCore
import sys
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setWindowTitle("Clickable Image in Menubar and Toolbar")
action = QtWidgets.QAction(
QtGui.QIcon("image.png"), "&Clickable Image", self)
action.triggered.connect(self.test)
menubar = self.menuBar()
menubar.addAction(action)
toolbar = QtWidgets.QToolBar("Toolbar")
toolbar.setIconSize(QtCore.QSize(20, 20))
toolbar.addAction(action)
self.addToolBar(toolbar)
def test(self):
print("Image clicked.")
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())