How to fix shortcuts in a PyQt5 code? - python

I'm using Ubuntu 14.04 and python 3.4.3 with PyQt 5.5.1. I've faced with a following problem,when I press Ctrl+Q noting happens.Coud you explain why does it happen and how to solve this problem. My code is below:
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QPushButton, QAction, QLineEdit, QMessageBox, QLabel
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import pyqtSlot, Qt
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 textbox - pythonspot.com'
self.left = 10
self.top = 10
self.width = 400
self.height = 140
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
mainMenu = self.menuBar()
fileMenu = mainMenu.addMenu('File')
editMenu = mainMenu.addMenu('Edit')
viewMenu = mainMenu.addMenu('View')
searchMenu = mainMenu.addMenu('Search')
toolsMenu = mainMenu.addMenu('Tools')
helpMenu = mainMenu.addMenu('Help')
exitButton = QAction(QIcon('exit24.png'), 'Exit', self)
exitButton.setShortcut('CTRL+Q')
exitButton.setStatusTip('Exit application')
exitButton.triggered.connect(self.close)
fileMenu.addAction(exitButton)
self.show()
#pyqtSlot()
def on_click(self):
textboxValue = self.textbox.text()
QMessageBox.question(self, 'Message - pythonspot.com', "You typed: " + textboxValue, QMessageBox.Ok, QMessageBox.Ok)
self.textbox.setText("")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())

Related

Bring to the front the MainWindow in Pyqt5

I am dealing with the following problem, while I am having multiple windows open, i would like to build a function linked to a button to bring to the front the Main window.
Thank you in advance.
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton,
QLabel)
class Window2(QMainWindow): # <===
def __init__(self):
super().__init__()
self.setWindowTitle("Window 2")
self.pushButton = QPushButton("Back to window1", self)
self.pushButton.clicked.connect(self.window1)
def window1(self): # <===
pass;
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "First Window"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.pushButton = QPushButton("Go to window 2 ", self)
self.pushButton.move(275, 200)
self.label = QLabel("window 1", self)
self.label.move(285, 175)
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.pushButton.clicked.connect(self.window2) # <===
def window2(self): # <===
self.w = Window2()
self.w.show()
def main():
app = QApplication(sys.argv)
window = Window()
window.show()
#app.exec_()
exit(app.exec_())
if __name__=='__main__':
main()
Regards
I am expecting a function to call back the widget "Window"
You could emit a signal from your second window that your fist window listens for, and calls .raise_() when triggered.
Update: Added a call to activateWindow in the first windows callback. thanks #musicmante
For example:
import sys
from PyQt5 import QtGui
from PyQt5.QtCore import pyqtSignal # import signal
from PyQt5.QtWidgets import (QApplication, QMainWindow, QPushButton,
QLabel)
class Window2(QMainWindow):
unfocus = pyqtSignal() # create signal
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setWindowTitle("Window 2")
self.pushButton = QPushButton("Back to window1", self)
# button press emits signal
self.pushButton.clicked.connect(self.unfocus.emit)
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "First Window"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
self.pushButton = QPushButton("Go to window 2 ", self)
self.pushButton.move(275, 200)
self.label = QLabel("window 1", self)
self.label.move(285, 175)
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.pushButton.clicked.connect(self.window2) # <===
def window2(self): # <===
self.w = Window2()
self.w.unfocus.connect(self.bring_to_top) # listen for signal and raise_ to top focus
self.w.show()
def bring_to_top(self):
self.activateWindow()
self.raise_()
def main():
app = QApplication(sys.argv)
window = Window()
window.show()
#app.exec_()
exit(app.exec_())
if __name__=='__main__':
main()

how to call the thread from a different function pyqt5

import sys
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QPlainTextEdit, QApplication, QMainWindow, QLabel, QComboBox
from PyQt5.QtGui import QPixmap
from pynput import keyboard
from pynput.keyboard import Listener, Controller
import pyperclip as pc
keyboard = Controller()
class App(QMainWindow):
def __init__(self, parent=None):
super(App, self).__init__(parent)
#super().__init__()
label = QLabel(self)
pixmap = QPixmap('E:/copycat/new.png')
label.setPixmap(pixmap)
label.setGeometry(0,0,900,400)
self.title = 'COPYCAT'
self.left = 10
self.top = 10
self.width = 400
self.height = 140
self.initUI()
self.key()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
###########
combo = QComboBox(self)
shotcut_list = ["Key.f9","Key.f2","Key.f3","Key.f4","Key.f5","Key.f6","Key.f7","Key.f8","Key.f1","Key.f10","Key.f11","Key.f12"]
combo.addItems(shotcut_list)
global shortcut
global cptext
shortcut = combo.currentText()
combo.setGeometry(350, 120, 120, 30)
combo.activated[str].connect(self.onChanged)
# Create textbox
self.textbox = QPlainTextEdit(self)
self.textbox.move(20, 160)
self.textbox.setReadOnly(True)
self.textbox.resize(500,205)
self.setGeometry(70,70,540,388)
self.show()
def onChanged(self, text):
global shortcut
shortcut=text
def print_key(self,key):
if str(key) == shortcut:
cptext = pc.paste()
keyboard.type(cptext)
self.textbox.insertPlainText(cptext)
self.textbox.insertPlainText("\n")
def key(self):
listener = Listener(on_press=self.print_key)
listener.start()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = App()
#ex.key()
sys.exit(app.exec_())
The above code shows an error when I update the textbox from the print_key function
It shows this error:
Cannot queue arguments of type 'QTextBlock'
(Make sure 'QTextBlock' is registered using qRegisterMetaType()
Cannot queue arguments of type 'QTextCursor'
(Make sure 'QTextCursor' is registered using qRegisterMetaType()
The callback associated with on_press is executed in a secondary thread so your implementation is updating the GUI from a secondary thread which Qt prohibits, instead you should use the signals as they are thread-safe.
import sys
import threading
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (
QApplication,
QComboBox,
QLabel,
QMainWindow,
QPlainTextEdit,
)
from pynput.keyboard import Listener, Controller
import pyperclip as pc
class KeyboardListener(QObject):
textChanged = pyqtSignal(str)
def __init__(self, shortcut, parent=None):
super().__init__(parent)
self._shortcut = shortcut
listener = Listener(on_press=self.handle_pressed)
listener.start()
self.mutex = threading.Lock()
#property
def shortcut(self):
return self._shortcut
def handle_pressed(self, key):
with self.mutex:
if str(key) == self.shortcut:
cptext = pc.paste()
self.textChanged.emit(cptext)
#pyqtSlot(str)
def update_shortcut(self, shortcut):
with self.mutex:
self._shortcut = shortcut
class App(QMainWindow):
def __init__(self, parent=None):
super(App, self).__init__(parent)
# super().__init__()
label = QLabel(self)
pixmap = QPixmap("E:/copycat/new.png")
label.setPixmap(pixmap)
label.setGeometry(0, 0, 900, 400)
self.title = "COPYCAT"
self.left = 10
self.top = 10
self.width = 400
self.height = 140
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
###########
combo = QComboBox(self)
shotcut_list = [
"Key.f9",
"Key.f2",
"Key.f3",
"Key.f4",
"Key.f5",
"Key.f6",
"Key.f7",
"Key.f8",
"Key.f1",
"Key.f10",
"Key.f11",
"Key.f12",
]
combo.addItems(shotcut_list)
shortcut = combo.currentText()
combo.setGeometry(350, 120, 120, 30)
self.textbox = QPlainTextEdit(self)
self.textbox.move(20, 160)
self.textbox.setReadOnly(True)
self.textbox.resize(500, 205)
self.setGeometry(70, 70, 540, 388)
self.keyboard = Controller()
self.listener = KeyboardListener(combo.currentText())
combo.activated[str].connect(self.listener.update_shortcut)
self.listener.textChanged.connect(self.handle_text_changed)
#pyqtSlot(str)
def handle_text_changed(self, text):
self.textbox.insertPlainText(text)
self.textbox.insertPlainText("\n")
self.keyboard.type(text)
def main():
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

Moving across elements using Up-Down keys

I make a program using PyQt5 and Python3.7. How to move across elements using arrow keys instead of tab key? (e.g. moving from button to textbox using down key)
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QLineEdit, QMainWindow, QPushButton, QFileSystemModel, QTreeView, \
QFileDialog, QComboBox
from PyQt5.QtCore import pyqtSlot
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
self.title = 'by Qt5 and python 3.7'
self.left = 10
self.top = 10
self.width = 1000
self.height = 500
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.label = QLabel('File Name: ')
self.label.move(20, 20)
self.btn_browse = QPushButton('Browse', self)
self.btn_browse.move(50, 20)
self.btn_browse.clicked.connect(self.on_click)
self.textbox = QLineEdit(self)
self.textbox.move(170, 20)
self.textbox.resize(280, 40)
self.page_view = QLineEdit(self)
self.page_view.move(20, 100)
self.page_view.resize(800, 400)
self.show()
#pyqtSlot()
def on_click(self):
print('PyQt5 button click')
# self.openFileNameDialog()
# self.saveFileDialog()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
One possible solution is to overwrite the keyPressEvent() method to detect the desired key and use focusNextPrevChild() by passing False or True if you want the focus to go to the previous or next widget, respectively.
from PyQt5.QtCore import pyqtSlot, Qt
class App(QMainWindow):
# ...
def keyPressEvent(self, e):
if e.key() == Qt.Key_Down:
self.focusNextPrevChild(True)
elif e.key() == Qt.Key_Up:
self.focusNextPrevChild(False)
# ...

How to add QVBoxLayout. around Qlabel and Qpushbutton ? pyqt5

How to add QVBoxLayout. around Qlabel and Qpushbutton?
I have this how can I add QVBoxLayout to make something like that
I have this code :
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication , QMainWindow , QPushButton ,
QToolTip , QLabel
import sys
class Window (QMainWindow):
def __init__(self):
super().__init__()
self.title = "pyQt5"
self.top = 100
self.left = 100
self.width = 680
self.height= 500
button = QPushButton("print", self)
button.move(200,200)
lb = QLabel('Hi', self)
lb.move(200,100)
self.s()
def s(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top,self.left,self.width,self.height)
self.show()
if __name__ == '__main__':
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
here image explains what I mean:
Try it:
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import (QApplication , QMainWindow , QPushButton ,
QToolTip , QLabel, QVBoxLayout, QWidget)
from PyQt5.QtCore import Qt
class Window (QMainWindow):
def __init__(self):
super().__init__()
self.title = "pyQt5"
self.top = 100
self.left = 100
self.width = 680
self.height= 500
self.main_widget = QWidget()
self.setCentralWidget(self.main_widget)
layout = QVBoxLayout(self.main_widget)
button = QPushButton("print", self)
button.setStyleSheet('background-color:blue; color:white; font-size:24px;')
lb = QLabel('Hello', self)
lb.setStyleSheet('background-color:green; color:white; font-size:24px;')
layout.addStretch(1)
layout.addWidget(lb)
layout.addStretch(1)
layout.addWidget(button)
layout.addStretch(1)
layout.setAlignment(Qt.AlignCenter)
self.s()
def s(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top,self.left,self.width,self.height)
self.show()
if __name__ == '__main__':
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

Matchbox-Keyboard on input for QLineEdit PyQT5

What I'm trying to do is when a user (via a touchscreen) clicks on an editable QEditLine I want it to show the Matchbox-Keyboard for user input. When it is not clicked do not show the keyboard.
I've gone through the C documentation, and a few C examples, but I'm lost as too make the jump to Python. I see people mentioning setting the "focus" can someone explain this too me?
import sys
import os
from PyQt5.QtWidgets import QApplication, QFileDialog, QSlider, QComboBox, QCheckBox, QWidget, QMainWindow, QPushButton, QLabel, QGridLayout, QGroupBox, QRadioButton, QMessageBox, QLineEdit
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import pyqtSlot, Qt
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'GUI TESTS'
self.left = 0
self.top = 0
self.width = 800
self.height = 400
self.statusBarMessage = "GUI TEST"
self.currentSprite = 'TEST.png'
self.btn1Active = False
self.btn2Active = False
self.btn3Active = False
self.btn4Active = False
self.btn5Active = False
self.btn6Active = False
self.btn7Active = False
self.btn8Active = False
self.saveLocationDir = ""
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.statusBar().showMessage(self.statusBarMessage)
self.userNameLabel = QLabel(self)
self.userNameLabel.move(0,125)
self.userNameLabel.setText("What is your name?")
self.userNameLabel.resize(120,20)
self.nameInput = QLineEdit(self)
self.nameInput.move(0,145)
self.nameInput.resize(200,32)
self.nameInput.setEchoMode(0)
#pyqtSlot()
def showKeyboard(self):
command = "matchbox-keyboard"
os.system(command)
It is not recommended to override the events method by assigning a function self.nameInput.mousePressEvent = self.showKeyboard since the tasks of the mousePressEvent of the QLineEdit are lost and could cause unexpected events.
Also, mousePressEvent is not the appropriate event since you can press the QLineEdit many times and it would be called back to the keyboard.
A better option is to launch it in focusInEvent and delete it in focusOutEvent:
import sys
import subprocess
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class MatchBoxLineEdit(QLineEdit):
def focusInEvent(self, e):
try:
subprocess.Popen(["matchbox-keyboard"])
except FileNotFoundError:
pass
def focusOutEvent(self,e):
subprocess.Popen(["killall","matchbox-keyboard"])
class App(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('GUI TESTS')
widget = QWidget()
self.setCentralWidget(widget)
lay = QVBoxLayout(widget)
self.userNameLabel = QLabel("What is your name?")
self.nameInput = MatchBoxLineEdit()
lay.addWidget(self.userNameLabel)
lay.addWidget(self.nameInput)
self.setGeometry(
QStyle.alignedRect(
Qt.LeftToRight,
Qt.AlignCenter,self.sizeHint(),
qApp.desktop().availableGeometry()
)
)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = App()
w.show()
sys.exit(app.exec_())
import sys
import os
from PyQt5.QtWidgets import QApplication, QFileDialog, QSlider, QComboBox, QCheckBox, QWidget, QMainWindow, QPushButton, QLabel, QGridLayout, QGroupBox, QRadioButton, QMessageBox, QLineEdit
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtCore import pyqtSlot, Qt
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'GUI TESTS'
self.left = 0
self.top = 0
self.width = 800
self.height = 400
self.statusBarMessage = "GUI TEST"
self.currentSprite = 'TEST.png'
self.btn1Active = False
self.btn2Active = False
self.btn3Active = False
self.btn4Active = False
self.btn5Active = False
self.btn6Active = False
self.btn7Active = False
self.btn8Active = False
self.saveLocationDir = ""
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.statusBar().showMessage(self.statusBarMessage)
self.userNameLabel = QLabel(self)
self.userNameLabel.move(0,125)
self.userNameLabel.setText("What is your name?")
self.userNameLabel.resize(120,20)
self.nameInput = QLineEdit(self)
self.nameInput.move(0,145)
self.nameInput.resize(200,32)
self.nameInput.setEchoMode(0)
self.nameInput.mousePressEvent=self.showKeyboard
#pyqtSlot()
def showKeyboard(self,event):
if event.button() == QtCore.Qt.LeftButton:
QtWidgets.QLineEdit.mousePressEvent(self, event)
command = "matchbox-keyboard"
os.system(command)
You can override mousePressEvent and achieve that functionality

Categories