I've just started doing Qt designing using python 3.x in Pycharms. I've watched a tuturial converting a .ui file to .py file. I'm good right now. I'm implementing a chat program.
Now, I want to type in TextEdit, linEdit but it dosen't wait for me type. I want to connect a keyboard or mouse event with them so when i click, it wait for me to type and when I hit Enter it stores the string.
The code between space and #here that's where I need help with. Basically I want to def methods for these events and calling them from them later.
My Ui_MainWindow class is as follows:
class Ui_MainWindow(QtGui.QMainWindow):
def __init__(self):
super(Ui_MainWindow,self).__init__()
self.setObjectName(_fromUtf8("MainWindow"))
self.resize(611, 487)
self.setTabShape(QtGui.QTabWidget.Rounded)
self.centralwidget = QtGui.QWidget(self)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.frame = QtGui.QFrame(self.centralwidget)
self.frame.setGeometry(QtCore.QRect(10, 30, 591, 41))
self.frame.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame.setFrameShadow(QtGui.QFrame.Raised)
self.frame.setObjectName(_fromUtf8("frame"))
self.label = QtGui.QLabel(self.frame)
self.label.setGeometry(QtCore.QRect(10, 10, 81, 17))
self.label.setObjectName(_fromUtf8("label"))
self.label_2 = QtGui.QLabel(self.frame)
self.label_2.setGeometry(QtCore.QRect(320, 10, 66, 17))
self.label_2.setObjectName(_fromUtf8("label_2"))
#Here
self.lineEdit = QtGui.QLineEdit(self.frame)
self.lineEdit.setGeometry(QtCore.QRect(90, 10, 221, 21))
self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
#Here
self.lineEdit_3 = QtGui.QLineEdit(self.frame)
self.lineEdit_3.setGeometry(QtCore.QRect(360, 10, 221, 21))
self.lineEdit_3.setObjectName(_fromUtf8("lineEdit_3"))
self.frame_2 = QtGui.QFrame(self.centralwidget)
self.frame_2.setGeometry(QtCore.QRect(10, 70, 291, 361))
self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtGui.QFrame.Raised)
self.frame_2.setObjectName(_fromUtf8("frame_2"))
#Here
self.textEdit = QtGui.QTextEdit(self.frame_2)
self.textEdit.setGeometry(QtCore.QRect(10, 10, 271, 301))
self.textEdit.setObjectName(_fromUtf8("textEdit"))
self.pushButton_3 = QtGui.QPushButton(self.frame_2)
self.pushButton_3.setGeometry(QtCore.QRect(10, 310, 161, 41))
self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
self.pushButton_4 = QtGui.QPushButton(self.frame_2)
self.pushButton_4.setGeometry(QtCore.QRect(180, 310, 98, 41))
self.pushButton_4.setObjectName(_fromUtf8("pushButton_4"))
self.pushButton_4.clicked.connect(self.clrLogs) # Clear Logs from WidgetList by clicking
self.verticalScrollBar = QtGui.QScrollBar(self.frame_2)
self.verticalScrollBar.setGeometry(QtCore.QRect(260, 10, 20, 301))
self.verticalScrollBar.setMinimumSize(QtCore.QSize(16, 301))
self.verticalScrollBar.setCursor(QtGui.QCursor(QtCore.Qt.SizeVerCursor))
self.verticalScrollBar.setAutoFillBackground(False)
self.verticalScrollBar.setOrientation(QtCore.Qt.Vertical)
self.verticalScrollBar.setInvertedAppearance(False)
self.verticalScrollBar.setObjectName(_fromUtf8("verticalScrollBar"))
######################################################
# Scroll to the bottom of chat windows
# self.textEdit.verticalScrollBar().setValue(self.textEdit.verticalScrollBar().maximum)
self.frame_3 = QtGui.QFrame(self.centralwidget)
self.frame_3.setGeometry(QtCore.QRect(300, 70, 301, 361))
self.frame_3.setFrameShape(QtGui.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtGui.QFrame.Raised)
self.frame_3.setObjectName(_fromUtf8("frame_3"))
self.listWidget = QtGui.QListWidget(self.frame_3)
self.listWidget.setGeometry(QtCore.QRect(10, 10, 281, 341))
self.listWidget.setObjectName(_fromUtf8("listWidget"))
self.verticalScrollBar_2 = QtGui.QScrollBar(self.frame_3)
self.verticalScrollBar_2.setGeometry(QtCore.QRect(270, 10, 21, 341))
self.verticalScrollBar_2.setOrientation(QtCore.Qt.Vertical)
self.verticalScrollBar_2.setObjectName(_fromUtf8("verticalScrollBar_2"))
self.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(self)
self.menubar.setGeometry(QtCore.QRect(0, 0, 611, 25))
self.menubar.setObjectName(_fromUtf8("menubar"))
self.menuMenu_Actions = QtGui.QMenu(self.menubar)
self.menuMenu_Actions.setObjectName(_fromUtf8("menuMenu_Actions"))
self.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(self)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
self.setStatusBar(self.statusbar)
self.actionVersion = QtGui.QAction(self)
self.actionVersion.setObjectName(_fromUtf8("actionVersion"))
self.actionVersion.triggered.connect(Chat.app_ver) # When submenu Action item Version is clicked
self.actionExit = QtGui.QAction(self)
self.actionExit.setObjectName(_fromUtf8("actionExit"))
self.actionExit.triggered.connect(qApp.quit) #When submenu Action item Exit is clicked
self.menuMenu_Actions.addAction(self.actionVersion)
self.menuMenu_Actions.addAction(self.actionExit)
self.menubar.addAction(self.menuMenu_Actions.menuAction())
self.retranslateUi(self)
QtCore.QMetaObject.connectSlotsByName(self)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", WindowTitle, None))
self.setWindowIcon(QtGui.QIcon('chat_icon'))
self.label.setText(_translate("MainWindow", "IP Address:", None))
self.label_2.setText(_translate("MainWindow", "Nick:", None))
self.pushButton_3.setText(_translate("MainWindow", "Send SMS", None))
self.pushButton_4.setText(_translate("MainWindow", "Clear Logs", None))
self.menuMenu_Actions.setTitle(_translate("MainWindow", "Menu Actions", None))
self.actionVersion.setText(_translate("MainWindow", "Version", None))
self.actionExit.setText(_translate("MainWindow", "Exit", None))
def clrLogs(self):
self.listWidget.clear()
The big left is TextEdit and rightmost is listWidget. I want to type in TextEdit and stores it and and send this msg to Chatlog(ListWidget).
I would start saying that you have to care about the following things:
Your keyboard UI, let's say a small prototype.
Be aware of who is getting your keyboard focus.
Take care of your filter to catch the events you need.
Send the right response to the claimant object from your keyboard.
I'd show your here some really nice example I've spent some considerable time to do and another one really simple and small. Since it's a quite amount of code I'd be leaving this small example and this more complex example from my github.
You can clone or copy and paste the code, just be sure it comes with the right imports if you copy and paste.
Edited[Added]
Here is the small example catching the events from the receiver you pass, and posting the equivalent events:
import sys
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtCore import QEvent
from PyQt5.QtCore import Qt
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QWidget
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.central_widget = QWidget()
self.cw_layout = QHBoxLayout()
self.central_widget.setLayout(self.cw_layout)
self.setCentralWidget(self.central_widget)
self.line = LineEdit()
self.kb = KeyBoard(self.line)
self.cw_layout.addWidget(self.line)
self.create_connections()
def create_connections(self):
self.line.signal_evoke_kb.connect(self.show_kb)
def show_kb(self):
if self.kb.isHidden():
self.kb.show()
else:
self.kb.hide()
class LineEdit(QLineEdit):
signal_evoke_kb = pyqtSignal()
def __init__(self):
super(LineEdit, self).__init__()
def mousePressEvent(self, QMouseEvent):
super(LineEdit, self).mousePressEvent(QMouseEvent)
self.signal_evoke_kb.emit()
class Key(QPushButton):
def __init__(self, name, event, receiver):
super(Key, self).__init__()
self.name = name
self.event = event
self.setText(name)
class KeyBoard(QWidget):
def __init__(self, receiver):
super(KeyBoard, self).__init__()
self.receiver = receiver
self.layout = QHBoxLayout()
self.keys = ['q','w','e','r','t','y']
self.dict_keys ={'q':Qt.Key_Q,'w':Qt.Key_W,'e':Qt.Key_E,'r':Qt.Key_R,'t':Qt.Key_T,'y':Qt.Key_Y,}
for key in self.keys:
key_keyboard = Key(key,self.dict_keys[key],receiver)
key_keyboard.clicked.connect(self.key_pressed)
self.layout.addWidget(key_keyboard)
self.setLayout(self.layout)
def key_pressed(self):
try:
event = QKeyEvent(QEvent.KeyPress, self.sender().event, Qt.NoModifier,
self.sender().name, False)
QCoreApplication.postEvent(self.receiver, event)
except Exception as e:
print(e)
def keyPressEvent(self, evt):
event = QKeyEvent(QEvent.KeyPress, evt.key(), evt.modifiers(),
evt.text(), False)
QCoreApplication.postEvent(self.receiver, event)
evt.ignore()
if __name__ == "__main__":
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
In this way you can personalize your key since your have your own Key, and organize it better when you need upper case and all else. If you are willing to do that I'd strongly recommend looking at the more complete example I linked before.
Related
I have been struggling to solve this problem within my pyqt program, I am making a program where the user can use their controllers as a mouse in python. However I am stuck in this part where the user can map individual controls with their corresponding keys window. To be more specific, whenever I launch this Dialog: "controllerMapping.py" in my mainWindow/app, any buttons and interactions with the dialog do not work. However when run "controllerMapping.py" directly as a standalone window, everything seems to work?
Here's the code for the MainWindow invokking controllerMapping.py:
def summon_controllerMapping(self):
# TODO: UNRESPONSIVE AS HELL
self.cm = QtWidgets.QDialog()
ui = controllerMapping.Ui_Dialog()
ui.setupUi(self.cm)
self.cm.show()
And here's the entire code for controllerMapping.py, I used the pyqt-designer to create the widget then added my own methods to hook for the buttons.
from PyQt6 import QtCore, QtGui, QtWidgets
import editMapping
import init_db
import mapping
preset_columns = init_db.get_table_columns("presets")
controls_columns = init_db.get_table_columns("mapping")
keybind_data = init_db.get_table_data("mapping")
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(500, 500)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(130, 440, 341, 32))
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
self.buttonBox.setObjectName("buttonBox")
self.desc_lbl = QtWidgets.QLabel(Dialog)
self.desc_lbl.setGeometry(QtCore.QRect(30, 30, 431, 16))
self.desc_lbl.setObjectName("desc_lbl")
self.mapping_table = QtWidgets.QTableWidget(Dialog)
self.mapping_table.setGeometry(QtCore.QRect(30, 70, 441, 291))
self.mapping_table.setObjectName("mapping_table")
self.mapping_table.setColumnCount(0)
self.mapping_table.setRowCount(0)
self.edit_btn = QtWidgets.QPushButton(Dialog)
self.edit_btn.setGeometry(QtCore.QRect(390, 360, 81, 24))
self.edit_btn.setObjectName("edit_btn")
self.selected_preset_lbl = QtWidgets.QLabel(Dialog)
self.selected_preset_lbl.setGeometry(QtCore.QRect(30, 400, 91, 21))
self.selected_preset_lbl.setObjectName("selected_preset_lbl")
self.presets_list = QtWidgets.QComboBox(Dialog)
self.presets_list.setGeometry(QtCore.QRect(130, 400, 161, 22))
self.presets_list.setObjectName("presets_list")
self.refresh_btn = QtWidgets.QPushButton(Dialog)
self.refresh_btn.setGeometry(QtCore.QRect(30, 360, 81, 24))
self.refresh_btn.setObjectName("refresh_btn")
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.presets_list.setCurrentIndex(-1)
self.populate_mapping_table()
self.populate_presets_list()
self.bind_btn()
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.desc_lbl.setText(_translate("Dialog", "Map Controls: Here is a list of controller buttons and their respective mapping"))
self.edit_btn.setText(_translate("Dialog", "Edit"))
self.selected_preset_lbl.setText(_translate("Dialog", "Selected Preset:"))
self.refresh_btn.setText(_translate("Dialog", "Refresh"))
def bind_btn(self):
self.edit_btn.clicked.connect(self.summon_editMapping)
self.presets_list.currentTextChanged.connect(self.set_new_preset)
def summon_editMapping(self):
self.em = QtWidgets.QDialog()
ui = editMapping.Ui_Dialog()
ui.setupUi(self.em)
self.em.show()
def populate_mapping_table(self):
print("mapping table")
column_cnt = len(preset_columns) + 1
keybinds_cnt = len(controls_columns) + 1
self.mapping_table.setColumnCount(column_cnt)
self.mapping_table.setRowCount(keybinds_cnt)
self.mapping_table.setItem(0, 0, QtWidgets.QTableWidgetItem("CONTROLS"))
for column, preset in enumerate(preset_columns):
self.mapping_table.setItem(0, column+1, QtWidgets.QTableWidgetItem(preset))
for row, controller in enumerate(controls_columns):
self.mapping_table.setItem(row+1, 0, QtWidgets.QTableWidgetItem(controller))
for column, keybinds in enumerate(keybind_data):
for row, keybind in enumerate(keybinds):
self.mapping_table.setItem(row+1, column+1, QtWidgets.QTableWidgetItem(keybind))
def populate_presets_list(self):
print("presets")
for preset in preset_columns:
self.presets_list.addItem(preset)
def set_new_preset(self):
print("Hello world")
"""selected_preset = self.presets_list.currentText()
print(selected_preset)
db = "databases/controls.db"
conn = sqlite3.connect(db)
for column in init_db.get_table_columns("presets"):
init_db.update_data("presets", column, False)
init_db.update_data("presets", selected_preset, True)
r = init_db.get_table_data("presets")
print(r)
conn.close()"""
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec())
I tried using putting print statements in the self.bind_btn() function, to no avail they did not work.
Every function except for self. Every method seems to be working fine except for self.bind_btn()
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'PyosUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (
QApplication,
QLabel,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget
)
class GameWindow(QWidget):
def __init__(self):
super.__init__()
layout = QVBoxLayout()
self.label = QLabel("Hello!")
layout.addWidget(self.label)
self.setLayout(layout)
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1044, 601)
self.Notepad = QtWidgets.QPushButton(Dialog)
self.Notepad.setGeometry(QtCore.QRect(50, 520, 281, 61))
self.Notepad.setObjectName("Notepad")
self.Game = QtWidgets.QPushButton(Dialog)
self.Game.setGeometry(QtCore.QRect(390, 520, 271, 61))
self.Game.setObjectName("Game")
self.Poweroff = QtWidgets.QPushButton(Dialog)
self.Poweroff.setGeometry(QtCore.QRect(690, 520, 111, 31))
self.Poweroff.setObjectName("Poweroff")
self.Settings = QtWidgets.QPushButton(Dialog)
self.Settings.setGeometry(QtCore.QRect(690, 560, 111, 31))
self.Settings.setObjectName("Settings")
self.Date_time = QtWidgets.QDateTimeEdit(Dialog)
self.Date_time.setGeometry(QtCore.QRect(840, 20, 194, 22))
self.Date_time.setObjectName("Date_time")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(0, -20, 1051, 641))
self.label.setText("")
self.label.setPixmap(QtGui.QPixmap("background.png"))
self.label.setObjectName("label")
self.label.raise_()
self.Notepad.raise_()
self.Game.raise_()
self.Poweroff.raise_()
self.Settings.raise_()
self.Date_time.raise_()
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
l = QVBoxLayout()
self.Game.clicked.connect(self.button_clicked)
l.addWidget(self.Game)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "PyOS"))
self.Notepad.setText(_translate("Dialog", "Notepad"))
self.Game.setText(_translate("Dialog", "Game"))
self.Poweroff.setText(_translate("Dialog", "Poweroff"))
self.Settings.setText(_translate("Dialog", "Settings"))
def game_window(self):
game_window = QtWidgets.QDialog()
game_window.setWindowTitle("Game")
game_window.resize(600, 600)
game_window.show()
def button_clicked(self):
self.game_window()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
The above code is the UI I made with Pyqt5 designer. For the work I want to make, when the 'Game' button is clicked, a window dedicated to the 'Game' button should appear.
However, when I run the code above, when I press the 'Game' button, a 600 x 600 window appears and then disappears.
Why?
How else can I solve this problem?
Thank you.
The game_window is a local variable within the game_window() method in Ui_Dialog.
Set the window as an instance and it should be fine.
Modified method
# other code remains same.
def game_window(self):
self._game_window = QtWidgets.QDialog()
self._game_window.setWindowTitle("Game")
self._game_window.resize(600, 600)
self._game_window.show()
Edit: The reason to add the underscore (_) is to avoid having the same name as the method name.
I have a QGraphicsView with a QGraphicsScene. On QGraphicsScene, I output the image using QGraphicsPixmapItem. And I would like to draw an ellipse over the image with my mouse.
I have that code now. And the ellipse is drawn on MainWindow.
What do I need to do to have the ellipse drawn on an image in QGraphicsView?
Code OFT_MainWindow
# OFT_MainWindow
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(862, 710)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.graphicsView = QtWidgets.QGraphicsView(self.centralwidget)
self.graphicsView.setGeometry(QtCore.QRect(10, 90, 841, 571))
self.graphicsView.setMouseTracking(True)
self.graphicsView.setObjectName("graphicsView")
self.buttonBox = QtWidgets.QDialogButtonBox(self.centralwidget)
self.buttonBox.setGeometry(QtCore.QRect(360, 670, 81, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.buttonBox.setFont(font)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(760, 10, 91, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.pushButton.setFont(font)
self.pushButton.setObjectName("pushButton")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(10, 10, 731, 31))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit_2.setGeometry(QtCore.QRect(10, 670, 331, 31))
self.lineEdit_2.setObjectName("lineEdit_2")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(10, 50, 841, 31))
font = QtGui.QFont()
font.setPointSize(10)
self.pushButton_2.setFont(font)
self.pushButton_2.setObjectName("pushButton_2")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "Browse"))
self.pushButton_2.setText(_translate("MainWindow", "Highlight field area"))
Main code
import OFT_MainWindow
import sys
import os
import numpy as np
import cv2
from PIL import Image, ImageQt, ImageEnhance
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QPoint
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.Qt import Qt
def main():
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
class MainWindow(QtWidgets.QMainWindow, OFT_MainWindow.Ui_MainWindow, QtWidgets.QGraphicsView, QtWidgets.QGraphicsScene):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.pushButton.clicked.connect(self.browse_file)
self.pushButton_2.clicked.connect(self.imageFrame)
self.begin = QtCore.QPoint()
self.end = QtCore.QPoint()
self.show()
###################################################################################
def browse_file(self):
self.lineEdit.clear()
file = QtWidgets.QFileDialog.getOpenFileName(self, "Choose file")
file = str(file[0])
if file:
self.lineEdit.setText(file) # добавить путь в lineEdit
# cap = cv2.VideoCapture(file)
###################################################################################
def imageFrame(self):
file = self.lineEdit.text()
self.drawing = False
self.lastPoint = QPoint()
scene = QtWidgets.QGraphicsScene(self)
self.image = QPixmap(file)
item = QtWidgets.QGraphicsPixmapItem(self.image)
scene.addItem(item)
view = self.graphicsView.setScene(scene)
# self.show()
def paintEvent(self, event):
qp = QtGui.QPainter(self)
br = QtGui.QBrush(QtGui.QColor(0, 255, 0, 25))
qp.setBrush(br)
ellipse = qp.drawEllipse(QtCore.QRect(self.begin, self.end))
coord_a = self.begin
coord_a = str(coord_a)
coord_a = coord_a[20:][:-1]
coord_b = self.end
coord_b = str(coord_b)
coord_b = coord_b[20:][:-1]
coord = ('begin = ' + coord_a + ' end = ' + coord_b)
self.lineEdit_2.setText(coord)
def mousePressEvent(self, event):
self.begin = event.pos()
self.end = event.pos()
self.update()
def mouseMoveEvent(self, event):
self.end = event.pos()
self.update()
###################################################################################
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
app.aboutToQuit.connect(app.deleteLater)
sys.exit(app.exec_())
If you want to paint something on a QGraphicsView, you have to add QGraphicsItem to its scene, otherwise you're making almost useless to crete a QGraphicsView to begin with.
One possible solution is to install an event filter on the scene, listen for mouse button events and draw an ellipse (using QGraphicsEllipseItem) on the scene if the first click is done within the contents of a QGraphicsPixmapItem.
Note that another possibility is to subclass from QGraphicsPixmapItem and implement its mouse events instead. It all depends on what you're going to do and what you're going to need from your program.
class MainWindow(QtWidgets.QMainWindow, OFT_MainWindow.Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
# ...
self.ellipseItem = None
def imageFrame(self):
# ...
scene.installEventFilter(self)
def eventFilter(self, source, event):
if event.type() == QtCore.QEvent.GraphicsSceneMousePress:
for item in self.graphicsView.scene().items(event.scenePos()):
if isinstance(item, QtWidgets.QGraphicsPixmapItem):
self.reference = item
self.ellipseItem = QtWidgets.QGraphicsEllipseItem(item)
self.ellipseItem.setBrush(QtGui.QColor(0, 255, 0, 25))
self.start = item.mapFromScene(event.scenePos())
elif event.type() == QtCore.QEvent.GraphicsSceneMouseMove and self.ellipseItem:
end = self.reference.mapFromScene(event.scenePos())
self.ellipseItem.setRect(QtCore.QRectF(self.start, end))
elif event.type() == QtCore.QEvent.GraphicsSceneMouseRelease and self.ellipseItem:
self.ellipseItem = None
return super().eventFilter(source, event)
Note that subclassing your Main window from all those classes (QtWidgets.QMainWindow, OFT_MainWindow.Ui_MainWindow, QtWidgets.QGraphicsView, QtWidgets.QGraphicsScene) is not only unnecessary and meaningless, but absolutely WRONG: multiple-inheritance subclassing should only be done when you know what you're inheriting from and why, otherwise, just don't. For Qt widgets that load from UI files, just subclass from the base widget class and the Ui.
I'm using a USB-barcode scanner to set the text of a Qt lineEdit field to scan production order number, My issue is that after scanning the window is closed instead of shifting to next lineEdit_2 to scan item number. How to setup lineEdit to shift the crusor to next lineEdit_2 and be ready for the next scan.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setGeometry(QtCore.QRect(290, 20, 81, 241))
self.buttonBox.setOrientation(QtCore.Qt.Vertical)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(50, 50, 113, 22))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(50, 120, 113, 22))
self.lineEdit_2.setObjectName("lineEdit_2")
self.lineEdit_3 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_3.setGeometry(QtCore.QRect(50, 200, 113, 22))
self.lineEdit_3.setObjectName("lineEdit_3")
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
By default the buttons of a QPushButton are pressed when the enter key is clicked and the QDialog has focus, and that click causes the rejected or accepted signal to be emitted, which closes the window, and this is handled by the default and autoDefault properties, so the first thing is to override that behavior.
On the other hand, pressing the enter key does not move to the other QLineEdit, in that case you must listen to that key and use focusNextPrevChild to move the focus.
Finally the codes generated by QtDesigner should not be modified so I will assume that the code you show is in the gui.py file, and I will implement the logic in main.py:
import sys
from PyQt5 import QtCore, QtWidgets
from gui import Ui_Dialog
class Dialog(QtWidgets.QDialog, Ui_Dialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.show()
for btn in self.buttonBox.buttons():
btn.setDefault(False)
btn.setAutoDefault(False)
btn.setFocusPolicy(QtCore.Qt.NoFocus)
def keyPressEvent(self, event):
if event.key() in (QtCore.Qt.Key_Enter, QtCore.Qt.Key_Return):
self.focusNextPrevChild(True)
super().keyPressEvent(event)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())
So I just started working with PyQt5. Right now I only programmed 1 button that's supposed to take text from a line edit, store it in a global variable and put it in a text browser. Now it does this... but with issues.
The text browser does NOT update until I click another program/window and then click my app again
When the line edit is cleared there is a bug which is basically text not being cleared properly but only it's top half. This goes away when I type again.
I tried calling the .update() methods for the widgets and QApplication.process_events()
Here's the code
from PyQt5 import QtCore, QtGui, QtWidgets
lyrics = ''
adlib = ' (Placeholder adlib)'
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(742, 680)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.addLineBtn = QtWidgets.QPushButton(self.centralwidget)
self.addLineBtn.setGeometry(QtCore.QRect(530, 0, 91, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setItalic(True)
self.addLineBtn.setFont(font)
self.addLineBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.addLineBtn.setObjectName("addLineBtn")
self.deleteBtn = QtWidgets.QPushButton(self.centralwidget)
self.deleteBtn.setGeometry(QtCore.QRect(120, 80, 91, 32))
self.deleteBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.deleteBtn.setObjectName("deleteBtn")
self.saveBtn = QtWidgets.QPushButton(self.centralwidget)
self.saveBtn.setGeometry(QtCore.QRect(30, 80, 91, 32))
self.saveBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.saveBtn.setObjectName("saveBtn")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setGeometry(QtCore.QRect(30, 20, 501, 51))
self.lineEdit.setObjectName("lineEdit")
self.dialLabel = QtWidgets.QLabel(self.centralwidget)
self.dialLabel.setGeometry(QtCore.QRect(640, 20, 71, 16))
self.dialLabel.setObjectName("dialLabel")
self.rtdSlider = QtWidgets.QSlider(self.centralwidget)
self.rtdSlider.setGeometry(QtCore.QRect(620, 40, 101, 22))
self.rtdSlider.setOrientation(QtCore.Qt.Horizontal)
self.rtdSlider.setObjectName("rtdSlider")
self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
self.textBrowser.setGeometry(QtCore.QRect(20, 120, 701, 501))
self.textBrowser.setObjectName("textBrowser")
self.noadlibBtn = QtWidgets.QPushButton(self.centralwidget)
self.noadlibBtn.setGeometry(QtCore.QRect(530, 50, 91, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setItalic(True)
self.noadlibBtn.setFont(font)
self.noadlibBtn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
self.noadlibBtn.setObjectName("noadlibBtn")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 742, 22))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.addLineBtn.clicked.connect(self.addLineAdlib)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.addLineBtn.setText(_translate("MainWindow", "Adlib"))
self.deleteBtn.setText(_translate("MainWindow", "Delete"))
self.saveBtn.setText(_translate("MainWindow", "Save"))
self.dialLabel.setText(_translate("MainWindow", "RTD Level"))
self.noadlibBtn.setText(_translate("MainWindow", "No Adlib"))
def addLineAdlib(self):
global lyrics
lyrics += self.lineEdit.text() + adlib + '\n'
self.lineEdit.clear()
self.textBrowser.setText(lyrics)
def addLineNoAdlib(self):
pass
def save(self):
pass
def deleteLine(self):
pass
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I found the same problem as yours and I use MacOS Mojave 10.14.6. This problem maybe due to OS, but I downgraded pyqt5 from the latest 5.14.1 to a stable version 5.9.2, the problem was solved.
This problem also happens with macos 10.15.6 + pyqt 5.15.0.
I created a small example with qtdesigner (with 1 lineEdit box, 1 label box, 1 button), and then created python file with pyuic5 as well as with pyside2-uic.
Both the generated python files have the same problem - when "click" is pressed I have to move out of the window and back again to see the results. But if I just press enter after the input text then it shows up immediately.
The problem is solved by adding an extra line in the main class, for repainting the GUI, as shown below:
import sys
from PyQt5.QtWidgets import QDialog, QApplication
from demo_ui_pyuic5 import *
class MyForm(QDialog):
def __init__(self):
super().__init__()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.buttonClick.clicked.connect(self.dispmessage)
self.show()
def dispmessage(self):
self.ui.labelResponse.setText("Hello " + self.ui.lineEditName.text())
self.ui.labelResponse.repaint() # this line added to fix the problem
if __name__=="__main__":
app = QApplication(sys.argv)
w = MyForm()
w.show()
sys.exit(app.exec_())
1. The text browser does NOT update until I click another program/window and then click my app again - this issue can be related with your OS. I have got incorrect PyQT5 behavior on Ubuntu 16.04 while on Ubuntu 18.04 everything was working fine. Can you share more info?
Note: I tested your script on Ubuntu 18.04, I didn't need to click another program/window to refresh it
2. When the line edit is cleared there is a bug which is basically text not being cleared properly but only it's top half. This goes away when I type again. - Can you explain what do you mean by it's top half? If you meant that there is still (Placeholder adlib) text, you should modify your function to check lineEdit textbox before adding something to lyrics variable. For example, like this:
def addLineAdlib(self):
if self.lineEdit.text():
global lyrics
lyrics += self.lineEdit.text() + adlib + '\n'
self.lineEdit.clear()
self.textBrowser.setText(lyrics)
Here is a cleaner more class-ified (more pythonic pyqt) version of your program I have left commented out stuff in for you to see where it would have been but I removed your coordinate system and replaced it with the more standard Layout style of creating a GUI.
I tested this using python 3.7 pyqt5 on win10 so if there is OS issue you will know it but my guess (without digging into that ugly mess) is that there was a disconnection some where which created the issue you were experiencing.
Also your button as designed will never create a blank line since its always putting something on a line -- I tested this by just clicking the button without entering anything
from sys import exit as sysExit
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, QCursor
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QDockWidget, QStyleFactory
from PyQt5.QtWidgets import QPushButton, QLineEdit, QLabel, QSlider, QTextBrowser, QMenuBar, QStatusBar
class MenuToolBar(QDockWidget):
def __init__(self, MainWin):
QDockWidget.__init__(self)
self.MainWin = MainWin
self.MainMenu = MainWin.menuBar()
# ******* Create the Help Menu *******
self.HelpMenu = self.MainMenu.addMenu('Help')
class CenterPanel(QWidget):
def __init__(self, parent):
QWidget.__init__(self)
# General Font Object for a couple of Buttons
btnFont = QFont()
btnFont.setFamily('Arial')
btnFont.setItalic(True)
# First Item Horizontal Box 1 Containing the AddLib Entry and Button
self.lnAdlibEntry = QLineEdit(self)
# self.lnAdlibEntry.setGeometry(QRect(30, 20, 501, 51))
# self.lnAdlibEntry.resize(501, 51)
self.btnAddLine = QPushButton(self)
# Left, Top, Width, Height
# self.btnAddLine.setGeometry(QRect(530, 0, 91, 51))
# Width, Height
# self.btnAddLine.resize(91, 51)
self.btnAddLine.setFont(btnFont)
self.btnAddLine.setCursor(QCursor(Qt.PointingHandCursor))
self.btnAddLine.setText('Adlib')
self.btnAddLine.clicked.connect(parent.AddLineAdlib)
HBox1 = QHBoxLayout()
HBox1.addWidget(self.lnAdlibEntry)
HBox1.addWidget(self.btnAddLine)
# Second Item Vertical Box 1 Containing the AdlibEntry LineEdit and RTD Label and RTD Slider
self.lblDial = QLabel(self)
# self.lblDial.setGeometry(QRect(640, 20, 71, 16))
# self.lblDial.resize(71, 16)
self.lblDial.setText("RTD Level")
self.sldrRtd = QSlider(self)
# self.sldrRtd.setGeometry(QRect(620, 40, 101, 22))
# self.sldrRtd.resize(101, 22)
self.sldrRtd.setOrientation(Qt.Horizontal)
VBox1 = QVBoxLayout()
VBox1.addWidget(self.lblDial)
VBox1.addWidget(self.sldrRtd)
# Third Item Horizontal Box 2 containing the Save, No Adlib and Delete buttons
self.btnNoAdlib = QPushButton(self)
# self.btnNoAdlib.setGeometry(QRect(530, 50, 91, 51))
# self.btnNoAdlib.resize(91, 51)
self.btnNoAdlib.setFont(btnFont)
self.btnNoAdlib.setCursor(QCursor(Qt.PointingHandCursor))
self.btnNoAdlib.setText("No Adlib")
self.btnSave = QPushButton(self)
# self.btnSave.setGeometry(QRect(30, 80, 91, 32))
# self.btnSave.resize(91, 32)
self.btnSave.setCursor(QCursor(Qt.PointingHandCursor))
self.btnSave.setText('Save')
self.btnDelete = QPushButton(self)
# self.btnDelete.setGeometry(QRect(120, 80, 91, 32))
# self.btnDelete.resize(91, 32)
self.btnDelete.setCursor(QCursor(Qt.PointingHandCursor))
self.btnDelete.setText('Delete')
HBox2 = QHBoxLayout()
HBox2.addWidget(self.btnSave)
HBox2.addStretch(1)
HBox2.addWidget(self.btnNoAdlib)
HBox2.addStretch(1)
HBox2.addWidget(self.btnDelete)
# Sixth Item Text Browser
self.txtBrowser = QTextBrowser(self)
# self.txtBrowser.setGeometry(QRect(20, 120, 701, 501))
# self.txtBrowser.resize(701, 501)
VBox2 = QVBoxLayout()
VBox2.addLayout(HBox1)
VBox2.addLayout(VBox1)
VBox2.addLayout(HBox2)
VBox2.addWidget(self.txtBrowser)
self.setLayout(VBox2)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.Lyrics = ''
self.Adlib = ' (Placeholder adlib)'
self.setWindowTitle('Main Window')
self.resize(742, 680)
self.CenterPane = CenterPanel(self)
self.setCentralWidget(self.CenterPane)
self.MenuBar = MenuToolBar(self)
# self.MenuBar.setGeometry(QRect(0, 0, 742, 22))
self.SetStatusBar(self)
self.setStyle(QStyleFactory.create('Cleanlooks'))
def SetStatusBar(self, parent):
StatusMsg = ''
parent.StatBar = parent.statusBar()
if len(StatusMsg) < 1:
StatusMsg = 'Ready'
parent.StatBar.showMessage(StatusMsg)
def AddLineAdlib(self):
# This statement retains everything previously in Lyrics and
# everything in the AdlibEntry box and everything in Adlib which
# I am not sure is what you are wanting but it is what you had
self.Lyrics += self.CenterPane.lnAdlibEntry.text() + self.Adlib + '\n'
self.CenterPane.lnAdlibEntry.clear()
self.CenterPane.txtBrowser.setText(self.Lyrics)
def AddLineNoAdlib(self):
pass
def Save(self):
pass
def DeleteLine(self):
pass
if __name__ == "__main__":
MainThred = QApplication([])
MainGUI = MainWindow()
MainGUI.show()
sysExit(MainThred.exec_())
Edited: I had an odd arrow appearing on my screen which it appears the QStyleFactory call removes and I adjust the StatusBar declaration to be more modular in case you want to Class-ify it later