I am new on PyQt I am working on a project on which I should implement a feature that make the user able to draw a digit using the mouse (digit recognition system). So what I want is when the mouse button is pressed the app will start to draw till the button is released. I made this source code but it is still not working (I think I am struggling with sending a signal to PaintEvent()).
import sys
from PyQt5 import QtCore
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QWidget, QInputDialog, QLineEdit, QFileDialog,QGraphicsView,QGraphicsScene,QVBoxLayout
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget)
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication
class Communicate(QObject):
drawApp = pyqtSignal()
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Simple')
self.setMouseTracking(True)
self.label = QLabel(self)
self.label.resize(500, 40)
self.c = Communicate()
self.c.drawApp.connect(self.PaintEvent())
self.show()
def mousePressEvent(self, event):
self.c.drawApp.emit()
self.startingposx = event.x()
self.startingposy = event.y()
#super().mousePressEvent(event)
print ("mouse pressed")
def mouseMoveEvent(self, event):
self.label.setText('Coordinates: ( %d : %d )' % (event.x(), event.y()) )
self.y = event.y()
self.x=event.x()
def PaintEvent(self,event):
qp = QPainter()
qp.begin(self)
#qp.setPen(Qt.red)
qp.drawPoints(self,qp)
qp.end()
self.update()
def mouseReleaseEvent(self,event):
self.endingposx = event.x()
self.endingposy = event.y()
super().mouseReleaseEvent(event)
print("starting point was",self.startingposx)
print("starting point y was ",self.startingposy)
print("ending point was ",self.endingposx)
print("ending point was y ",self.endingposy)
print("released")
def drawPoints(self,qp):
qp.setPen(Qt.red)
size = self.size()
x=self.x
y=self.y
qp.drawPoint(x,y)
app = QApplication(sys.argv)
widget = MyWidget()
widget.show()
app.exec_()
Python is sensitive to uppercase and lowercase so be more careful, the method is called paintEvent.
Also you should not call paintEvent directly, you must use the function update(), this method will internally call paintEvent().
But even correcting that error your problem is not solved, if you want to draw a path it is advisable to use QPainterPath as this stores the strokes.
class Drawer(QWidget):
newPoint = pyqtSignal(QPoint)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.path = QPainterPath()
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPath(self.path)
def mousePressEvent(self, event):
self.path.moveTo(event.pos())
self.update()
def mouseMoveEvent(self, event):
self.path.lineTo(event.pos())
self.newPoint.emit(event.pos())
self.update()
def sizeHint(self):
return QSize(400, 400)
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setLayout(QVBoxLayout())
label = QLabel(self)
drawer = Drawer(self)
drawer.newPoint.connect(lambda p: label.setText('Coordinates: ( %d : %d )' % (p.x(), p.y())))
self.layout().addWidget(label)
self.layout().addWidget(drawer)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.show()
sys.exit(app.exec_())
Screenshot:
I don't have the reputation to reply to eyllanesc's solution, but in case others are having issues, the imports were not complete. Here's is eyllanesc's solution with the imports. It will execute without error:
import sys
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import (QLabel, QWidget)
from PyQt5.QtGui import QPainter, QPainterPath
from PyQt5.QtCore import pyqtSignal, QPoint, QSize
from PyQt5.QtWidgets import QApplication
class Drawer(QWidget):
newPoint = pyqtSignal(QPoint)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.path = QPainterPath()
def paintEvent(self, event):
painter = QPainter(self)
painter.drawPath(self.path)
def mousePressEvent(self, event):
self.path.moveTo(event.pos())
self.update()
def mouseMoveEvent(self, event):
self.path.lineTo(event.pos())
self.newPoint.emit(event.pos())
self.update()
def sizeHint(self):
return QSize(400, 400)
class MyWidget(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setLayout(QVBoxLayout())
label = QLabel(self)
drawer = Drawer(self)
drawer.newPoint.connect(lambda p: label.setText('Coordinates: ( %d : %d )' % (p.x(), p.y())))
self.layout().addWidget(label)
self.layout().addWidget(drawer)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWidget()
w.show()
sys.exit(app.exec_())
Related
I have opened a image in a QHBoxLayout. I need to crop the opened image and save the cropped image. How I can do this in PySide?
import sys
from PySide import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
hbox = QtGui.QHBoxLayout(self)
pixmap = QtGui.QPixmap("re.png")
lbl = QtGui.QLabel(self)
lbl.setPixmap(pixmap)
self.rect = QtCore.QRect()
hbox.addWidget(lbl)
self.setLayout(hbox)
self.setGeometry(300, 300, 280, 170)
self.setWindowTitle('Open Image')
self.show()
# Tried here to implement Qpen
#self.painter = QtGui.QPainter(self)
#self.painter.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine));
#self.painter.drawRect(self.rect);
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I suggest use class QtGui.QRubberBand to select area of image to crop. (PySide also implements the same functionality as PyQt)
First, implement method mouseMoveEvent (self, QMouseEvent), mouseReleaseEvent (self, QMouseEvent) and mousePressEvent (self, QMouseEvent) (More infomation read in QtGui.QRubberBand class reference).
Next, get last geometry of QtGui.QRubberBand to crop image by use QRect QWidget.geometry (self).
Last, Use QPixmap QPixmap.copy (self, QRect rect = QRect()) to crop image by put geometry from crop area. And save image it by use bool QPixmap.save (self, QString fileName, str format = None, int quality = -1).
Example;
import sys
from PyQt4 import QtGui, QtCore
class QExampleLabel (QtGui.QLabel):
def __init__(self, parentQWidget = None):
super(QExampleLabel, self).__init__(parentQWidget)
self.initUI()
def initUI (self):
self.setPixmap(QtGui.QPixmap('input.png'))
def mousePressEvent (self, eventQMouseEvent):
self.originQPoint = eventQMouseEvent.pos()
self.currentQRubberBand = QtGui.QRubberBand(QtGui.QRubberBand.Rectangle, self)
self.currentQRubberBand.setGeometry(QtCore.QRect(self.originQPoint, QtCore.QSize()))
self.currentQRubberBand.show()
def mouseMoveEvent (self, eventQMouseEvent):
self.currentQRubberBand.setGeometry(QtCore.QRect(self.originQPoint, eventQMouseEvent.pos()).normalized())
def mouseReleaseEvent (self, eventQMouseEvent):
self.currentQRubberBand.hide()
currentQRect = self.currentQRubberBand.geometry()
self.currentQRubberBand.deleteLater()
cropQPixmap = self.pixmap().copy(currentQRect)
cropQPixmap.save('output.png')
if __name__ == '__main__':
myQApplication = QtGui.QApplication(sys.argv)
myQExampleLabel = QExampleLabel()
myQExampleLabel.show()
sys.exit(myQApplication.exec_())
I would use QImage's copy method:
im2 = im.copy(self.rect)
im2.save(...)
import sys
from PyQt5 import QtGui, QtCore,QtWidgets
from PyQt5.QtWidgets import QRubberBand, QLabel, QApplication, QWidget
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QRect
class QExampleLabel (QLabel):
def __init__(self, parentQWidget = None):
super(QExampleLabel, self).__init__(parentQWidget)
self.initUI()
def initUI (self):
self.setPixmap(QPixmap('input.png'))
def mousePressEvent (self, eventQMouseEvent):
self.originQPoint = eventQMouseEvent.pos()
self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self)
self.currentQRubberBand.setGeometry(QRect(self.originQPoint, QtCore.QSize()))
self.currentQRubberBand.show()
def mouseMoveEvent (self, eventQMouseEvent):
self.currentQRubberBand.setGeometry(QRect(self.originQPoint, eventQMouseEvent.pos()).normalized())
def mouseReleaseEvent (self, eventQMouseEvent):
self.currentQRubberBand.hide()
currentQRect = self.currentQRubberBand.geometry()
self.currentQRubberBand.deleteLater()
cropQPixmap = self.pixmap().copy(currentQRect)
cropQPixmap.save('output.png')
if __name__ == '__main__':
myQApplication = QApplication(sys.argv)
myQExampleLabel = QExampleLabel()
myQExampleLabel.show()
sys.exit(myQApplication.exec_())
I am trying to figure out a way to customize the scrollbars for QListWidget to have the scrollbars above and below the QListWidget instead of the normal vertical and horizontal scrollbars.
Please check out my example below if you don't understand what I mean.
In the example below I use QPushButtons with QTimers controlling the scrolling in place of the scrollbars but what I am looking for are scrollbars like the ones in QMenu when menu scrolling is enabled.
If that is not an option, I am wondering if there is a scrollbar signal or something that I could try to use to know when the scrollbars are normally activated? That way I can show/hide the buttons as needed. Thanks.
import sys
from PyQt5.QtCore import pyqtSignal, QTimer, Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, \
QApplication, QStyle, QListWidget, QStyleOptionButton, QListWidgetItem
class UpBtn(QPushButton):
mouseHover = pyqtSignal()
def __init__(self):
QPushButton.__init__(self)
self.setMouseTracking(True)
self.timer = QTimer()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
opt = QStyleOptionButton()
self.initStyleOption(opt)
self.style().drawControl(QStyle.CE_ScrollBarSubLine, opt, painter, self)
painter.end()
def startScroll(self):
self.mouseHover.emit()
def enterEvent(self, event):
self.timer.timeout.connect(self.startScroll)
self.timer.start(120)
def leaveEvent(self, event):
self.timer.stop()
class DwnBtn(QPushButton):
mouseHover = pyqtSignal()
def __init__(self):
QPushButton.__init__(self)
self.setMouseTracking(True)
self.timer = QTimer()
def paintEvent(self, event):
painter = QPainter()
painter.begin(self)
opt = QStyleOptionButton()
self.initStyleOption(opt)
self.style().drawControl(QStyle.CE_ScrollBarAddLine, opt, painter, self)
painter.end()
def startScroll(self):
self.mouseHover.emit()
def enterEvent(self, event):
self.timer.timeout.connect(self.startScroll)
self.timer.start(120)
def leaveEvent(self, event):
self.timer.stop()
class Window(QWidget):
def __init__(self):
super(Window, self).__init__()
self.layout = QVBoxLayout()
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
self.upBtn = UpBtn()
self.upBtn.setFixedWidth(230)
self.layout.addWidget(self.upBtn)
self.listWidget = QListWidget()
self.listWidget.setFixedWidth(230)
self.listWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.listWidget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.layout.addWidget(self.listWidget)
self.downBtn = DwnBtn()
self.downBtn.setFixedWidth(230)
self.layout.addWidget(self.downBtn)
self.setLayout(self.layout)
self.upBtn.clicked.connect(self.upBtnClicked)
self.upBtn.mouseHover.connect(self.upBtnClicked)
self.downBtn.clicked.connect(self.downBtnClicked)
self.downBtn.mouseHover.connect(self.downBtnClicked)
for i in range(100):
item = QListWidgetItem()
item.setText("list item " + str(i))
self.listWidget.addItem(item)
def upBtnClicked(self):
cur = self.listWidget.currentRow()
self.listWidget.setCurrentRow(cur - 1)
def downBtnClicked(self):
cur = self.listWidget.currentRow()
self.listWidget.setCurrentRow(cur + 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())
EDIT:
Here is an example image for what I am talking about. This is a scrollable QMenu.
EDIT:
Scrollable QMenu code.
Uncomment the commented parts to get a fixed size like in the image. Normally Qmenu scrolling only works when the menu items exceed the screen height. I am just looking for the top and bottom hover style scrolling but to be used in QListWidget.
import sys
from PyQt5.QtCore import QPoint, QEvent
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, \
QApplication, QAction, QMenu, QProxyStyle, QStyle
class MyMenu(QMenu):
def event(self, event):
if event.type() == QEvent.Show:
self.move(self.parent().mapToGlobal(QPoint(-108, 0)))
return super(MyMenu, self).event(event)
# class CustomStyle(QProxyStyle):
# def pixelMetric(self, QStyle_PixelMetric, option=None, widget=None):
# if QStyle_PixelMetric == QStyle.PM_MenuScrollerHeight:
# return 15
# if QStyle_PixelMetric == QStyle.PM_MenuDesktopFrameWidth:
# return 290
# else:
# return QProxyStyle.pixelMetric(self, QStyle_PixelMetric, option, widget)
class MainWindow(QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.layout = QVBoxLayout()
self.btn = QPushButton("Button")
self.btn.setFixedHeight(30)
self.btn.setFixedWidth(100)
self.myMenu = MyMenu("Menu", self.btn)
self.btn.setMenu(self.myMenu)
self.layout.addWidget(self.btn)
self.setLayout(self.layout)
menus = []
for _ in range(5):
myMenus = QMenu("Menu"+str(_+1), self.btn)
# myMenus.setFixedHeight(120)
myMenus.setStyleSheet("QMenu{menu-scrollable: 1; }")
menus.append(myMenus)
for i in menus:
self.btn.menu().addMenu(i)
for item in range(100):
action = QAction("item" + str(item), self)
i.addAction(action)
if __name__ == '__main__':
app = QApplication(sys.argv)
# app.setStyle(CustomStyle())
w = MainWindow()
w.show()
app.exec_()
The idea is to obtain the row of the upper and lower element that will decide whether the buttons are hidden or not, for that we use the method itemAt () that returns the item given the geometrical coordinates. On the other hand I have improved this calculation has to do every time they change the number of items in the QListView for that we use the signals of the internal model.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Button(QtWidgets.QPushButton):
moveSignal = QtCore.pyqtSignal()
def __init__(self, *args, **kwargs):
super(Button, self).__init__(*args, **kwargs)
self.m_timer = QtCore.QTimer(self, interval=120)
self.m_timer.timeout.connect(self.moveSignal)
self.setMouseTracking(True)
self.setFixedHeight(20)
def mouseReleaseEvent(self, e):
super(Button, self).mousePressEvent(e)
self.setDown(True)
def enterEvent(self, e):
self.setDown(True)
self.m_timer.start()
super(Button, self).enterEvent(e)
def leaveEvent(self, e):
self.setDown(False)
self.m_timer.stop()
super(Button, self).leaveEvent(e)
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.setFixedWidth(230)
icon = self.style().standardIcon(QtWidgets.QStyle.SP_ArrowUp)
self.upBtn = Button(icon=icon)
self.upBtn.moveSignal.connect(self.moveUp)
icon = self.style().standardIcon(QtWidgets.QStyle.SP_ArrowDown)
self.downBtn = Button(icon=icon)
self.downBtn.moveSignal.connect(self.moveDown)
self.listWidget = QtWidgets.QListWidget()
self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
layout = QtWidgets.QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
layout.addWidget(self.upBtn)
layout.addWidget(self.listWidget)
layout.addWidget(self.downBtn)
self.adjust_buttons()
self.create_connections()
def create_connections(self):
self.listWidget.currentItemChanged.connect(self.adjust_buttons)
model = self.listWidget.model()
model.rowsInserted.connect(self.adjust_buttons)
model.rowsRemoved.connect(self.adjust_buttons)
model.rowsMoved.connect(self.adjust_buttons)
model.modelReset.connect(self.adjust_buttons)
model.layoutChanged.connect(self.adjust_buttons)
#QtCore.pyqtSlot()
def adjust_buttons(self):
first = self.listWidget.itemAt(QtCore.QPoint())
r = self.listWidget.row(first)
self.upBtn.setVisible(r != 0 and r!= -1)
last = self.listWidget.itemAt(self.listWidget.viewport().rect().bottomRight())
r = self.listWidget.row(last)
self.downBtn.setVisible( r != (self.listWidget.count() -1) and r != -1)
#QtCore.pyqtSlot()
def moveUp(self):
ix = self.listWidget.moveCursor(QtWidgets.QAbstractItemView.MoveUp, QtCore.Qt.NoModifier)
self.listWidget.setCurrentIndex(ix)
#QtCore.pyqtSlot()
def moveDown(self):
ix = self.listWidget.moveCursor(QtWidgets.QAbstractItemView.MoveDown, QtCore.Qt.NoModifier)
self.listWidget.setCurrentIndex(ix)
#QtCore.pyqtSlot(str)
def add_item(self, text):
item = QtWidgets.QListWidgetItem(text)
self.listWidget.addItem(item)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = Window()
for i in range(100):
window.add_item("item {}".format(i))
window.show()
sys.exit(app.exec_())
This question already exists:
How to make the picture zoom (QGraphicsItem), and make scrollbars change their size accordingly (QGraphicsScene)? [duplicate]
Closed 4 years ago.
How to add a pixmap drawn in QGraphicsItem to QGraphicsScene in the following example?
#!/usr/bin/env python
from PyQt5.QtCore import QRectF, Qt
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QGraphicsItem, QGraphicsView, QGraphicsScene, QMainWindow
class TicTacToe(QGraphicsItem):
def __init__(self, helper):
super(TicTacToe, self).__init__()
self.mypixmap = QPixmap("exit.png")
def paint(self, painter, option, widget):
painter.setOpacity(1)
painter.drawPixmap(0,0, 300, 300, self.mypixmap)
def boundingRect(self):
return QRectF(0,0,300,300)
class MyGraphicsView(QGraphicsView):
def __init__(self):
super(MyGraphicsView, self).__init__()
scene = QGraphicsScene(self)
self.tic_tac_toe = TicTacToe(self)
scene.addItem(self.tic_tac_toe)
self.setScene(scene)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.y = MyGraphicsView()
self.setCentralWidget(self.y)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Example()
w.show()
sys.exit(app.exec_())
Try it:
Drag and drop image,
Enlarge Image -> Qt.Key_Right,
Reduce image <- Qt.Key_Left.
from PyQt5.QtCore import (QLineF, QPointF, QRectF,
pyqtSignal, QStandardPaths, Qt)
from PyQt5.QtGui import (QIcon, QBrush, QColor, QPainter, QPixmap)
from PyQt5.QtWidgets import (QAction, QMainWindow, QApplication,
QGraphicsObject,
QGraphicsView, QGraphicsScene, QGraphicsItem,
QGridLayout, QVBoxLayout, QHBoxLayout,
QFileDialog, QLabel, QLineEdit, QPushButton)
from PyQt5.QtOpenGL import QGLFormat
class MyGraphicsView(QGraphicsView):
backgroundColor = QColor(28, 31, 34) # Background color
def __init__(self):
super(MyGraphicsView, self).__init__()
self.resize(800, 600)
self.setBackgroundBrush(self.backgroundColor)
self.setCacheMode(self.CacheBackground)
self.setRenderHints(
QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
if QGLFormat.hasOpenGL():
self.setRenderHint(QPainter.HighQualityAntialiasing)
self.setViewportUpdateMode(self.SmartViewportUpdate)
self._scene = QGraphicsScene(-400, -300, 800, 600, self)
self.setScene(self._scene)
self._itemImage = None
def keyReleaseEvent(self, event):
""" Button processing event """
self._scaleImage(event)
super(MyGraphicsView, self).keyReleaseEvent(event)
def closeEvent(self, event):
""" Clear all items in the scene when the window is `closed` """
self._scene.clear()
self._itemImage = None
super(MyGraphicsView, self).closeEvent(event)
def _scaleImage(self, event):
""" Image zoom operation """
if not self._itemImage:
return
scale = self._itemImage.scale()
if event.key() == Qt.Key_Right:
# Enlarge Image -> Qt.Key_Right
if scale >= 0.91:
return
self._itemImage.setScale(scale + 0.1)
elif event.key() == Qt.Key_Left:
# Reduce image <- Qt.Key_Left
if scale <= 0.11:
return
self._itemImage.setScale(scale - 0.1)
def loadImage(self):
path, _ = QFileDialog.getOpenFileName(
self, 'Please select an image',
QStandardPaths.writableLocation(QStandardPaths.DesktopLocation),
'Image(*.jpg *.png)')
if not path:
return
if self._itemImage:
# Delete previous item
self._scene.removeItem(self._itemImage)
del self._itemImage
self._itemImage = self._scene.addPixmap(QPixmap(path))
self._itemImage.setFlag(QGraphicsItem.ItemIsMovable)
self._itemImage.setScale(0.1) # Default load factor
size = self._itemImage.pixmap().size()
# Adjust the image in the middle
self._itemImage.setPos(
-size.width() * self._itemImage.scale() / 2,
-size.height() * self._itemImage.scale() / 2
)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = MyGraphicsView()
w.show()
ww = QPushButton('Select a file', clicked=w.loadImage)
ww.show()
sys.exit(app.exec_())
A picture is displayed with scrollbars on a window. We can draw on it. I want to add a menubar to the same window. I tried the following, it didn't work. Nothing is shown on the window when I run this.
#!/usr/bin/env python
from PyQt5.QtCore import (QLineF, QPointF, QRectF, Qt)
from PyQt5.QtGui import (QIcon, QBrush, QColor, QPainter, QPixmap)
from PyQt5.QtWidgets import (QAction, QMainWindow, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem,
QGridLayout, QVBoxLayout, QHBoxLayout,
QLabel, QLineEdit, QPushButton)
class TicTacToe(QGraphicsItem):
def __init__(self):
super(TicTacToe, self).__init__()
def paint(self, painter, option, widget):
painter.setPen(Qt.black)
painter.drawLine(0,100,300,100)
def boundingRect(self):
return QRectF(0,0,300,300)
def mousePressEvent(self, event):
pos = event.pos()
self.select(int(pos.x()/100), int(pos.y()/100))
self.update()
super(TicTacToe, self).mousePressEvent(event)
class MyGraphicsView(QGraphicsView):
def __init__(self):
super(MyGraphicsView, self).__init__()
scene = QGraphicsScene(self)
self.tic_tac_toe = TicTacToe()
scene.addItem(self.tic_tac_toe)
scene.addPixmap(QPixmap("exit.png"))
self.setScene(scene)
self.setCacheMode(QGraphicsView.CacheBackground)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
def keyPressEvent(self, event):
key = event.key()
if key == Qt.Key_R:
self.tic_tac_toe.reset()
super(MyGraphicsView, self).keyPressEvent(event)
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.y = MyGraphicsView()
self.initUI()
def initUI(self):
menubar = self.menuBar()
menu = menubar.addMenu('File')
db_action = menu.addAction("Open file")
self.setGeometry(30, 30, 30, 20)
self.setWindowTitle('Menubar')
self.show()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
mainWindow = Example()
mainWindow.showFullScreen()
sys.exit(app.exec_())
A widget is shown in a window if it is a child of some component of the window, in your case self.y is not the child of Example, but only an attribute, a possible solution is to set it as centralWidget:
class Example(QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.y = MyGraphicsView()
self.setCentralWidget(self.y)
self.initUI()
def initUI(self):
menubar = self.menuBar()
menu = menubar.addMenu('File')
db_action = menu.addAction("Open file")
self.setGeometry(30, 30, 30, 20)
self.setWindowTitle('Menubar')
self.show()
I'm new to PyQt and I'm trying to use it to create a widget that returns the position of the mouse in real time.
Here's what I have:
import sys
from PyQt5.QtWidgets import (QWidget, QToolTip,
QPushButton, QApplication)
from PyQt5.QtGui import QFont
class MouseTracker(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.setMouseTracking(True)
self.installEventFilter(self)
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Mouse Tracker')
self.show()
def eventFilter(self, source, event):
if (event.type() == QtCore.QEvent.MouseMove and
event.buttons() == QtCore.Qt.NoButton):
pos = event.pos()
print('Mouse coords: ( %d : %d )' % (pos.x(), pos.y()))
return QtGui.QWidget.eventFilter(self, source, event)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MouseTracker()
sys.exit(app.exec_())
I'm confused on how to make this work. I set mouse tracking to True but I'm not sure how to apply the event filter. Any help?
The QMouseEvent function must be implemented since it is executed when the mouse is moved.
import sys
from PyQt5.QtWidgets import (QApplication, QLabel, QWidget)
class MouseTracker(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.setMouseTracking(True)
def initUI(self):
self.setGeometry(300, 300, 300, 200)
self.setWindowTitle('Mouse Tracker')
self.label = QLabel(self)
self.label.resize(200, 40)
self.show()
def mouseMoveEvent(self, event):
self.label.setText('Mouse coords: ( %d : %d )' % (event.x(), event.y()))
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MouseTracker()
sys.exit(app.exec_())