I just started to learn how to build a GUI using PyQt5.
I trace some example on the internet and trying to create a GUI for practice.
But I have a problem when I tried to show a text next to the Editor.
I follow the way that I found on the internet but it just not working.
can anyone tell me how to fix it?
I comment the part that I am trying to show the text in my code
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import xml.etree.cElementTree as ET
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 = 200
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create textbox
self.textbox = QLineEdit(self)
#self.textbox.setAlignment(Qt.AlignRight)
self.textbox.move(80, 20)
self.textbox.resize(200,40)
self.textbox2 = QLineEdit(self)
self.textbox2.move(80, 80)
self.textbox2.resize(200,40)
#####################################
# the part i am trying to show text #
#####################################
txt1 = QLabel("case indes",self)
txt1.setAlignment(Qt.AlignCenter)
mytext = QFormLayout()
mytext.addRow(txt1,self.textbox) # not showing in Aligned position
mytext.addRow("Case type",tbox2) # not working
# Create a button in the window
self.button = QPushButton('Show text', self)
self.button.move(20,150)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.center()
self.show()
#pyqtSlot()
def on_click(self):
textboxValue = self.textbox.text()
textboxValue2 = self.textbox2.text()
QMessageBox.question(self, 'Message - pythonspot.com', "You typed: " + textboxValue + " , second msg is: " + textboxValue2, QMessageBox.Ok, QMessageBox.Ok)
print(textboxValue)
self.textbox.setText("")
self.textbox2.setText("")
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
The layouts are used to manage the position and size of the widgets so you should not use move or resize, you have never established which widget the layout belongs to and finally QMainWindow is a special widget in which you must establish a centralwidget. In the next section there is the solution:
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
central_widget = QWidget()
self.setCentralWidget(central_widget)
# Create textbox
self.textbox = QLineEdit()
self.textbox2 = QLineEdit()
txt1 = QLabel("case indes",self)
txt1.setAlignment(Qt.AlignCenter)
mytext = QFormLayout(central_widget)
mytext.addRow(txt1, self.textbox) # not showing in Aligned position
mytext.addRow("Case type", self.textbox2) # not working
# Create a button in the window
self.button = QPushButton('Show text')
mytext.addRow(self.button)
# connect button to function on_click
self.button.clicked.connect(self.on_click)
self.center()
self.show()
Related
In a PyQt5 application I have a QMenu. I want to make it so that once the menu is open, users can use keys 1, 2, 3, etc to select option 1, 2, 3, etc in the menu. However, I'm having trouble setting the shortcut, or getting the shortcut to react to the keypress.
I've taken an example from this website, and adapted it slightly to show my issue. I tried assigning shortcuts in the addAction function, but this does not work.
I've tried creating regular QShortcuts, but those no longer respond when the menu is open. I noticed that I can change the selected option using arrow up and down, and then confirm my selection with the enter key, so the QMenu is able to catch keypresses. But how can I assign my own shortcuts?
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
import sys
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "PyQt5 Context Menu"
self.top = 200
self.left = 500
self.width = 400
self.height = 300
self.InitWindow()
def InitWindow(self):
self.setWindowIcon(QtGui.QIcon("icon.png"))
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
newAct = contextMenu.addAction("New", self.triggered, shortcut='A')
openAct = contextMenu.addAction("Open", self.triggered2, shortcut='B')
quitAct = contextMenu.addAction("Quit", self.triggered3, shortcut='C')
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
self.close()
def triggered(self):
print("triggered 1")
def triggered2(self):
print("triggered 2")
def triggered3(self):
print("triggered 3")
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
When a QMenu is opened, shortcuts are not active, but accelerator keys are working. You declare them with &:
newAct = contextMenu.addAction("New &1", self.triggered)
When the context menu pops up, pressing 1 triggers the correct function.
The QKeySequence class encapsulates a key sequence as used by shortcuts.
More... https://doc.qt.io/qt-5/qkeysequence.html
Try it:
import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.title = "PyQt5 Context Menu"
self.top = 200
self.left = 500
self.width = 400
self.height = 300
self.InitWindow()
def InitWindow(self):
self.setWindowIcon(QtGui.QIcon("icon.png"))
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
# newAct = contextMenu.addAction("New", self.triggered, shortcut='A')
newAct = contextMenu.addAction(
"New (&A)", self.triggered, shortcut=QtGui.QKeySequence.New) # +++
openAct = contextMenu.addAction(
"Open (&B)", self.triggered2, shortcut=QtGui.QKeySequence.Open) # +++
quitAct = contextMenu.addAction(
"Quit (&C)", self.triggered3, shortcut=QtGui.QKeySequence.Quit) # +++
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
self.close()
def triggered(self):
print("triggered 1")
def triggered2(self):
print("triggered 2")
def triggered3(self):
print("triggered 3")
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
I want users of my app to be able to press the button, and then keep typing. With QLineEdit.selectAll(), I am able to select the text entered after Run is pressed, but typing won't do anything. See:
The text is selected due to QLineEdit.selectAll(), but typing won't do anything.
Here's what I have so far:
from PyQt5.QtWidgets import *
import sys
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.title = 'window title'
self.left = 10
self.top = 10
self.width = 400
self.height = 75
self.initUI()
self.layout = QVBoxLayout()
self.line = QLineEdit()
label = QLabel('Enter a WORD:')
run_button = QPushButton('Run')
self.layout.addWidget(label)
self.layout.addWidget(self.line)
self.layout.addWidget(run_button)
widget = QWidget()
widget.setLayout(self.layout)
run_button.clicked.connect(self.on_click)
self.setCentralWidget(widget)
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
def on_click(self):
response = QLabel(self.line.text())
self.layout.addWidget(response)
self.line.selectAll()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
selectAll() is tricky. It looks like the widget has the focus, but it doesn't. Use setFocus(). Order doesn't matter in this case
self.line.setFocus()
self.line.selectAll()
or
self.line.selectAll()
self.line.setFocus()
Further, in this UI, you can hook up the returnPressed signal of self.line to on_click so that when the user presses enter/return in self.line, the on_click method runs.
self.line.returnPressed.connect(self.on_click)
Putting it all together:
from PyQt5.QtWidgets import *
import sys
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.left = 10
self.top = 10
self.width = 400
self.height = 75
self.initUI()
self.layout = QVBoxLayout()
self.line = QLineEdit()
label = QLabel('Enter a WORD:')
run_button = QPushButton('Run')
reset_button = QPushButton('Reset History')
self.label = QLabel()
self.layout.addWidget(label)
self.layout.addWidget(self.line)
self.layout.addWidget(run_button)
self.layout.addWidget(reset_button)
self.layout.addWidget(self.label)
widget = QWidget()
widget.setLayout(self.layout)
run_button.clicked.connect(self.on_click)
self.line.returnPressed.connect(self.on_click)
reset_button.clicked.connect(self.reset_click)
self.setCentralWidget(widget)
def initUI(self):
self.setGeometry(self.left, self.top, self.width, self.height)
def on_click(self):
self.label.setText(self.label.text() + '\n' + self.line.text())
self.line.setFocus()
self.line.selectAll()
def reset_click(self):
self.label.setText('')
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
By using this:
self.line.selectAll()
self.line.grabKeyboard()
It will select the text entered at every push of the button, and you will be able to continue typing without clicking in the textbox.
I need two PyQt windows to run in the same time on a multiple display machine: one screen for display and the other for input.
In the following example i'm trying to have a simple window with a button and another window with a label. When i push the button, the other windows label text should change:
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QApplication, QWidget, QDialog, QInputDialog,QDesktopWidget,QVBoxLayout,QPushButton,QMainWindow,QAction,QFileDialog,QGroupBox,QGridLayout,QLabel
class Control_Pannel(QWidget):
def __init__(self):
super().__init__()
self.title = 'Main Control Pannel'
self.left = 10
self.top = 10
self.width = 640
self.height = 400
self.text = "Display text"
self.InitializeUI()
def InitializeUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)
self.inputBox = QGroupBox("Display")
layout = QGridLayout()
layout.setColumnStretch(1, 4)
layout.setColumnStretch(2, 4)
button = QPushButton('Push here to change text')
layout.addWidget(button,0,0)
button.clicked.connect(self.on_click)
self.inputBox.setLayout(layout)
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.inputBox)
self.setLayout(windowLayout)
self.show()
app = QApplication(sys.argv)
ex=InputWindows()
sys.exit(app.exec_())
#pyqtSlot()
def on_click(self):
InputWindows.text = "Modified text after button push"
print(InputWindows.text)
InputWindows.update()
##???? here i don't know how to make the changes be reflected in the other window, even if when i print the .text attribute it seems to have changed.
class InputWindows(QDialog):
def __init__(self):
super().__init__()
self.title = 'Display Pannel'
self.left = 5
self.top = 5
self.width = 300
self.height = 300
self.text = "Original Text"
self.InitializeUI()
def InitializeUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)
self.createDisplayGridLayout()
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
self.show()
def createDisplayGridLayout(self):
self.horizontalGroupBox = QGroupBox("Grid")
layout = QGridLayout()
layout.setColumnStretch(1, 4)
layout.setColumnStretch(2, 4)
self.label = QLabel(self.text)
layout.addWidget(self.label,0,0)
if __name__=='__main__':
app=QApplication(sys.argv)
ex=Control_Pannel()
sys.exit(app.exec_())
With InputWindows.update() i'm getting that first argument of unbound method must have a type QWidget and if i try InputWindows.label.update() i'm getting type object inputwindows has no attribute label
InputWindows is a class, it is an abstraction so you generally have to create an object, I ask you: if you have n Windows InputWindows, to which window would you update the text ?, we would not know, so by simple logic we see that it is wrong to do it. On the other hand, consider each class as a black box where it is stimulated by inputs, and outputs are obtained, in your case Control_Pannel must have an output: the new text, but that output is asynchronous since it changes and must be used when changing , and that in Qt is a signal, so we must create it. On the other hand, InputWindows must receive the information to create a slot that updates the text in the QLabel as shown below:
import sys
from PyQt5 import QtCore, QtWidgets
class Control_Pannel(QtWidgets.QWidget):
sendSignal = QtCore.pyqtSignal(str)
def __init__(self):
super().__init__()
self.title = 'Main Control Pannel'
self.left = 10
self.top = 10
self.width = 640
self.height = 400
self.text = "Display text"
self.InitializeUI()
def InitializeUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)
self.inputBox = QtWidgets.QGroupBox("Display")
layout = QtWidgets.QGridLayout()
layout.setColumnStretch(1, 4)
layout.setColumnStretch(2, 4)
button = QtWidgets.QPushButton('Push here to change text')
layout.addWidget(button,0,0)
button.clicked.connect(self.on_click)
self.inputBox.setLayout(layout)
windowLayout = QtWidgets.QVBoxLayout(self)
windowLayout.addWidget(self.inputBox)
#QtCore.pyqtSlot()
def on_click(self):
text = "Modified text after button push"
self.sendSignal.emit(text)
class InputWindows(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.title = 'Display Pannel'
self.left = 5
self.top = 5
self.width = 300
self.height = 300
self.InitializeUI()
self.setText("Original Text")
#QtCore.pyqtSlot(str)
def setText(self, text):
self.label.setText(text)
def InitializeUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left,self.top,self.width,self.height)
self.createDisplayGridLayout()
windowLayout = QtWidgets.QVBoxLayout(self)
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
def createDisplayGridLayout(self):
self.horizontalGroupBox = QtWidgets.QGroupBox("Grid")
layout = QtWidgets.QGridLayout()
layout.setColumnStretch(1, 4)
layout.setColumnStretch(2, 4)
self.label = QtWidgets.QLabel()
layout.addWidget(self.label, 0, 0)
self.horizontalGroupBox.setLayout(layout)
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
ex1 = Control_Pannel()
ex1.show()
ex2 = InputWindows()
ex2.show()
ex1.sendSignal.connect(ex2.setText)
sys.exit(app.exec_())
I have been trying to build a simple GUI with:
A QLineEdit where the user writes a string
A QPushButton that clears whatever the user writes in the above lineedit every time I click on it.
My issue is in the second one. I have been trying to solve it by looking at solutions online but they weren't really useful so far. Can anyone give a hint on how to proceed?
Here is my code:
import sys
from PyQt5.QtWidgets import QWidget, QLineEdit
from PyQt5.QtWidgets import QLabel, QPushButton, QApplication
from PyQt5.QtCore import pyqtSlot
app = QApplication(sys.argv)
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'MyApp'
self.left = 10
self.top = 10
self.width = 800
self.height = 800
self.initUI()
self.show()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create textbox for index number 1
self.nameLabel = QLabel(self)
self.nameLabel.setText('Insert something:')
self.nameLabel.move(20, 80)
self.textbox_index1 = QLineEdit(self)
self.textbox_index1.move(20, 100)
self.textbox_index1.resize(280, 40)
# Create a button in the window
self.buttonC1 = QPushButton('Clear', self)
self.buttonC1.move(300, 119)
# connect buttons "CLEAR" to function
self.buttonC1.clicked.connect(self.on_clickC1)
#pyqtSlot()
# Functions for the CLEAR buttons
def on_clickC1(self):
self.x1 = clearSearch1(self.textbox_index1.text(''))
return self.x1
def clearSearch1(self.x):
return self.x.clear()
if __name__ == '__main__':
app.aboutToQuit.connect(app.deleteLater)
ex = App()
sys.exit(app.exec_())
Thanks so much in advance,
Mattia
I do not understand what you are trying to do, the solution is simple, you must connect the clicked signal to the clear method directly without creating any other function:
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'MyApp'
self.left, self.top, self.width, self.height = 10, 10, 800, 800
self.initUI()
self.show()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# Create textbox for index number 1
self.nameLabel = QLabel(self)
self.nameLabel.setText('Insert something:')
self.nameLabel.move(20, 80)
self.textbox_index1 = QLineEdit(self)
self.textbox_index1.move(20, 100)
self.textbox_index1.resize(280, 40)
# Create a button in the window
self.buttonC1 = QPushButton('Clear', self)
self.buttonC1.move(300, 119)
# connect buttons "CLEAR" to function
self.buttonC1.clicked.connect(self.textbox_index1.clear)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
The Problem:
I am trying to find a way of adding a font style to text that as written by the user of my PyQt5 text editor program. I don't want to code each font into some kind of menu manually and I am wondering if there is a built-in way for the user to select their font style for their text like this (Notepad font picker):
My code currently looks like this:
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'Text Editor'
self.left = 10
self.top = 10
self.width = 1080
self.height = 920
self.widget = QWidget(self)
self.lbl = QLabel(self)
self.text = QTextEdit(self.widget)
self.widget.setLayout(QVBoxLayout())
self.widget.layout().addWidget(self.text)
self.setCentralWidget(self.widget)
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
toolBar = self.menuBar()
fileMenu = toolBar.addMenu('File')
editMenu = toolBar.addMenu('Edit')
toolsMenu = toolBar.addMenu('Tools')
helpMenu = toolBar.addMenu('Help')
fontButton = QAction('Configure Editor', self)
fontButton.setShortcut('Ctrl+E')
fontButton.triggered.connect(lambda: self.font_set)
toolsMenu.addAction(fontButton)
self.show()
def font_set(self):
print("Display Fonts")
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Qt has a widget called QFontDialog, and that is perfect for this case, in the following part I show an example of its use:
def font_set(self):
font, ok = QFontDialog.getFont(self.text.font(), self)
if ok:
#QApplication.setFont(font)
self.text.setFont(font)
print("Display Fonts", font)
Note: You must change the following statement:
fontButton.triggered.connect(lambda: self.font_set)
to:
fontButton.triggered.connect(self.font_set)
Screenshot: