Change QLabelText as QLineEdit text changes - python

There is this QLineEdit with setText is set to a predefined value and there is a QDialog with QLabel in it which is supposed to show whatever is in the QLineEdit. The code below shows the situation.
import sys
import os
import datetime
from PySide2.QtWidgets import *
from PySide2 import *
now = datetime.datetime.now()
now_str = now.strftime("%H.%M.%S,%d/%m/%y")
default_text = (str("Sugar_" + now_str))
class MainWindow(QWidget):
def __init__(self):
super(MainWindow, self).__init__()
self.resize(600, 500)
btn = QPushButton("show dialog")
mw_layout = QVBoxLayout()
mw_layout.addWidget(btn)
self.setLayout(mw_layout)
btn.clicked.connect(show_d)
class dialog(QDialog):
def __init__(self):
super(dialog, self).__init__()
self.resize(400, 350)
title = QLineEdit()
title.setText(default_text)
show_title = QPushButton("Show title")
cancel = QPushButton("Cancel")
d_layout = QVBoxLayout()
d_layout.addWidget(title)
d_layout.addWidget(show_title)
d_layout.addWidget(cancel)
self.setLayout(d_layout)
t = title.text()
title_dialog = QDialog()
label = QLabel()
label.setText("The title is " + title.text())
ok = QPushButton("OK!")
t_layout = QVBoxLayout()
t_layout.addWidget(label)
t_layout.addWidget(ok)
title_dialog.setLayout(t_layout)
def show_t():
title_dialog.exec_()
title_dialog.setModal(True)
def close_t():
title_dialog.accept()
show_title.clicked.connect(show_t)
ok.clicked.connect(close_t)
cancel.clicked.connect(self.close_d)
def close_d(self):
self.reject()
def show_d():
d = dialog()
d.exec_()
d.setModal(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow = MainWindow()
MainWindow.show()
sys.exit(app.exec_())
But this doesn't work like I expected it to. The QLabel text just show the default text even when the text in QLineEdit is changed.
The console also shows the following error;
qt.xkb.compose: failed to create compose table.
I think there is something's obviously wrong but I can't seem to find what.
Any help appreciated.

You must update the text before a certain event, for example an instant before displaying the dialog:
class dialog(QDialog):
def __init__(self):
super(dialog, self).__init__()
self.resize(400, 350)
self.title_lineedit = QLineEdit(default_text)
show_title = QPushButton("Show title")
cancel = QPushButton("Cancel")
d_layout = QVBoxLayout(self)
d_layout.addWidget(self.title_lineedit)
d_layout.addWidget(show_title)
d_layout.addWidget(cancel)
self.title_dialog = QDialog()
self._title_label = QLabel()
ok = QPushButton("OK!")
t_layout = QVBoxLayout(self.title_dialog)
t_layout.addWidget(self._title_label)
t_layout.addWidget(ok)
show_title.clicked.connect(self.on_clicked)
ok.clicked.connect(self.title_dialog.reject)
cancel.clicked.connect(self.reject)
self.update_label()
def update_label(self):
self._title_label.setText("The title is " + self.title_lineedit.text())
def on_clicked(self):
self.update_label()
self.title_dialog.exec_()

Related

How to activate Key Press Event, in Pyqt5?

Here is my Code. I want to capture a pressed key and print it. But Nothing will Happen, How to resolve it? I Have two classes. One is Create_Instance and another one is Main_Window. In My code, I have Only Lable items to display. How to activate it?
Edited
import sys
from PyQt5.QtWidgets import *
class Create_Instance(QWidget):
def __init__(self,dict_item):
super().__init__()
self.dict_items = dict_item
self.lbl = QLabel("This is My Label")
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.lbl)
self.setLayout(self.vbox)
def keyPressEvent(self, event):
print(event)
print(self.dict_items)
class Main_Window(QWidget):
def __init__(self):
super(). __init__()
self.setWindowTitle("Main Window")
self.layout_main = QHBoxLayout()
self.firstmenu_container = Create_Instance(dict_item="1")
self.secondmenu_container = Create_Instance(dict_item="2")
self.layout_main.addWidget(self.firstmenu_container)
self.layout_main.addWidget(self.secondmenu_container)
self.setLayout(self.layout_main)
def main():
app = QApplication(sys.argv)
ex = Main_Window()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You must add the widget to the layout:
def __init__(self):
super().__init__()
self.setWindowTitle("Main Window")
self.layout_main = QHBoxLayout()
self.firstmenu_container = Create_Instance(dict_item="1")
self.layout_main.addWidget(self.firstmenu_container)
self.secondmenu_container = Create_Instance(dict_item="2")
self.layout_main.addWidget(self.secondmenu_container)
self.setLayout(self.layout_main)

How to open a new MDI sub-window in PyQt5?

What I want to do is to open a new Countrypage sub-window by clicking on the "New" button which is in Countrypage itself.
For example, if I click the "New" button in a CountryPage window (window title: "Country page"), one more new Countrypage window will be opened in the MDI area (window title: "Country Page 1"). Now if we click the "New" button in "Country Page 1", one more new window will open in the MDI area (window title: "Country page 2") and so on - and I want to close the windows one by one by pressing the corresponding "Close" button in Countrypage. New window are opened only by pressing a "New" button.
And if we close the last opened window by pressing the "Close" button, the text item in the "Country" text-box will be automatically updated in the previous window's "Country" text-box and so on.
Main Script :
import sys,os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from sample_countrypage import Countrypage
class MainPage(QMainWindow):
count = 0
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
self.mdi.setFixedSize(1000,400)
self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setWindowTitle(" Sample Programme")
self.setGeometry(100,100,1600,600)
self.Ui()
self.show()
def Ui(self):
self.btn1=QPushButton("Country")
self.btn1.setFixedSize(100, 30)
self.btn1.clicked.connect(self.countrypage)
self.left_layout = QVBoxLayout()
self.right_layout = QHBoxLayout()
self.main_layout = QHBoxLayout()
self.left_layout.setContentsMargins(3,5,5,3)
self.left_layout.addWidget(self.btn1)
self.left_layout.addStretch()
self.right_layout.addWidget(self.mdi)
self.main_layout.setSpacing(5)
self.main_layout.setContentsMargins(0,0,0,0)
self.main_layout.addLayout(self.left_layout)
self.main_layout.addLayout(self.right_layout)
self.main_layout.addStretch()
widget = QWidget()
widget.setLayout(self.main_layout)
self.setCentralWidget(widget)
self.subwindow1 = QMdiSubWindow()
self.subwindow1.setObjectName("SubWindow_1")
# self.subwindow1.setWindowFlag(Qt.FramelessWindowHint)
print(Countrypage.btn2click)
def countrypage(self):
self.countrywindow = Countrypage()
self.subwindow1.setWidget(self.countrywindow)
self.subwindow1.setWindowTitle("Create Country")
self.subwindow1.setFixedWidth(300)
self.mdi.addSubWindow(self.subwindow1)
self.subwindow1.show()
self.mdi.cascadeSubWindows()
self.countrywindow.closeRequsted.connect(self.subwindow1close)
def subwindow1close(self):
print("close activated from mdi programme")
self.subwindow1.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
mainwindow = MainPage()
app.setStyle("Windows")
mainwindow.show()
sys.exit(app.exec_())
Countrypage.py
import sys,os
from PyQt5.QtWidgets import QWidget,QApplication,QPushButton,QLineEdit,QFormLayout,QVBoxLayout,QHBoxLayout
from PyQt5.QtCore import pyqtSignal
class Countrypage(QWidget):
closeRequsted = pyqtSignal()
def __init__(self):
super().__init__()
self.btn1 = QPushButton("close")
self.btn2 = QPushButton("New")
self.btn1.clicked.connect(self.result)
self.btn2.clicked.connect(self.btn2click)
self.tb_country = QLineEdit()
self.tb_continent =QLineEdit()
self.form_layout = QFormLayout()
self.form_layout.addRow("Country",self.tb_country)
self.form_layout.addRow("continent",self.tb_continent)
self.form_layout.addRow("",self.btn2)
self.form_layout.addRow("",self.btn1)
self.setLayout(self.form_layout)
def result(self):
self.closeRequsted.emit()
def btn2click(self):
btn2text = (self.btn2.text())
print(btn2text)
if __name__=="__main__":
app = QApplication(sys.argv)
countrywin = Countrypage()
countrywin.show()
sys.exit(app.exec_())
The adding and closing of sub-windows is best handled by the main-window. The CountryPage class doesn't need to know anything about the sub-windows. The new/close buttons can be directly connected to methods of the main-window. This makes it easier to manage the sub-windows via the functions of the mdi-area.
Below is a re-write of your example which should do what you asked for:
Main Script:
import sys, os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class MainPage(QMainWindow):
def __init__(self):
super().__init__()
self.mdi = QMdiArea()
self.mdi.setFixedSize(1000, 400)
self.mdi.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.mdi.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setWindowTitle("Sample Programme")
self.setGeometry(100, 100, 1600, 600)
self.Ui()
def Ui(self):
self.btn1 = QPushButton("Country")
self.btn1.setFixedSize(100, 30)
self.btn1.clicked.connect(self.countrypage)
self.left_layout = QVBoxLayout()
self.right_layout = QHBoxLayout()
self.main_layout = QHBoxLayout()
self.left_layout.setContentsMargins(3, 5, 5, 3)
self.left_layout.addWidget(self.btn1)
self.left_layout.addStretch()
self.right_layout.addWidget(self.mdi)
self.main_layout.setSpacing(5)
self.main_layout.setContentsMargins(0, 0, 0, 0)
self.main_layout.addLayout(self.left_layout)
self.main_layout.addLayout(self.right_layout)
self.main_layout.addStretch()
widget = QWidget()
widget.setLayout(self.main_layout)
self.setCentralWidget(widget)
def countrypage(self):
page = Countrypage()
subwindow = self.mdi.addSubWindow(page)
subwindow.setWindowTitle("Create Country")
subwindow.setFixedWidth(300)
page.btn_close.clicked.connect(self.subwindowclose)
page.btn_new.clicked.connect(self.countrypage)
subwindow.show()
self.mdi.cascadeSubWindows()
def subwindowclose(self):
print("close activated from mdi programme")
current = self.mdi.activeSubWindow()
if current is not None:
self.mdi.activatePreviousSubWindow()
previous = self.mdi.activeSubWindow()
if previous is not None:
previous.widget().update_fields(current.widget())
current.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
mainwindow = MainPage()
app.setStyle("Windows")
mainwindow.show()
sys.exit(app.exec_())
Countrypage.py:
import sys,os
from PyQt5.QtWidgets import QWidget,QApplication,QPushButton,QLineEdit,QFormLayout,QVBoxLayout,QHBoxLayout
from PyQt5.QtCore import pyqtSignal
class Countrypage(QWidget):
def __init__(self):
super().__init__()
self.btn_close = QPushButton("Close")
self.btn_new = QPushButton("New")
self.tb_country = QLineEdit()
self.tb_continent = QLineEdit()
self.form_layout = QFormLayout()
self.form_layout.addRow("Country", self.tb_country)
self.form_layout.addRow("Continent", self.tb_continent)
self.form_layout.addRow("", self.btn_close)
self.form_layout.addRow("", self.btn_new)
self.setLayout(self.form_layout)
def update_fields(self, other):
if isinstance(other, Countrypage):
self.tb_country.setText(other.tb_country.text())
self.tb_continent.setText(other.tb_continent.text())
else:
raise TypeError('invalid page type')

Make QGroupBox selectable and clickable

I have the following toy interface:
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
my_tree = QtWidgets.QTreeWidget()
layout.addWidget(my_tree)
alpha = QtWidgets.QTreeWidgetItem(my_tree, ['Alpha'])
beta = QtWidgets.QTreeWidgetItem(my_tree, ['Beta'])
alpha.addChild(QtWidgets.QTreeWidgetItem(['one']))
alpha.addChild(QtWidgets.QTreeWidgetItem(['two']))
beta.addChild(QtWidgets.QTreeWidgetItem(['first']))
beta.addChild(QtWidgets.QTreeWidgetItem(['second']))
my_tree.expandAll()
alpha.child(0).setSelected(True)
scroll = QtWidgets.QScrollArea()
layout.addWidget(scroll)
scrollLayout = QtWidgets.QVBoxLayout()
scrollW = QtWidgets.QWidget()
scroll.setWidget(scrollW)
scrollW.setLayout(scrollLayout)
scrollLayout.setAlignment(QtCore.Qt.AlignTop)
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
for _ in range(5):
fooGroup = QtWidgets.QGroupBox()
fooLayout = QtWidgets.QVBoxLayout()
fooGroup.setLayout(fooLayout)
fooItem1 = QtWidgets.QLabel("fooItem1")
fooItem2 = QtWidgets.QLabel("fooItem2")
fooItem3 = QtWidgets.QLabel("fooItem3")
fooLayout.addWidget(fooItem1)
fooLayout.addWidget(fooItem2)
fooLayout.addWidget(fooItem3)
scrollLayout.addWidget(fooGroup)
self.show()
app = QtWidgets.QApplication([])
window = MainWindow()
app.exec_()
How can I make each group in the scroll area selectable and clickable by the user?
I have so far tried to add the following code in the loop:
def onFooGroupClick():
print("Group")
fooGroup.clicked.connect(onFooGroupClick)
and (as per this post):
def onFooGroupClick():
print("Group")
def f():
return onFooGroupClick()
fooGroup.mousePressEvent = f()
However, all my efforts have been unsuccessful and I cannot seem to be able to make it work.
Create a class that inherits from QGroupBox.
Define the clicked signal in it and override the mousePressEvent method.
from PyQt5 import QtWidgets, QtGui, QtCore
class GroupBox(QtWidgets.QGroupBox): # +++ !!!
clicked = QtCore.pyqtSignal(str, object) # +++
def __init__(self, title):
super(GroupBox, self).__init__()
self.title = title
self.setTitle(self.title)
def mousePressEvent(self, event):
child = self.childAt(event.pos())
if not child:
child = self
self.clicked.emit(self.title, child) # +++
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
w = QtWidgets.QWidget()
layout = QtWidgets.QVBoxLayout()
w.setLayout(layout)
self.setCentralWidget(w)
my_tree = QtWidgets.QTreeWidget()
layout.addWidget(my_tree)
alpha = QtWidgets.QTreeWidgetItem(my_tree, ['Alpha'])
beta = QtWidgets.QTreeWidgetItem(my_tree, ['Beta'])
alpha.addChild(QtWidgets.QTreeWidgetItem(['one']))
alpha.addChild(QtWidgets.QTreeWidgetItem(['two']))
beta.addChild(QtWidgets.QTreeWidgetItem(['first']))
beta.addChild(QtWidgets.QTreeWidgetItem(['second']))
my_tree.expandAll()
alpha.child(0).setSelected(True)
scroll = QtWidgets.QScrollArea()
layout.addWidget(scroll)
scrollLayout = QtWidgets.QVBoxLayout()
scrollW = QtWidgets.QWidget()
scroll.setWidget(scrollW)
scrollW.setLayout(scrollLayout)
scrollLayout.setAlignment(QtCore.Qt.AlignTop)
scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
scroll.setWidgetResizable(True)
for _ in range(5):
fooGroup = GroupBox(f'GroupBox_{_}') # - QtWidgets.QGroupBox()
fooGroup.setObjectName(f'fooGroup {_}')
fooGroup.clicked.connect(self.onFooGroupClick) # +++
fooLayout = QtWidgets.QVBoxLayout()
fooGroup.setLayout(fooLayout)
fooItem1 = QtWidgets.QLabel("fooItem1", objectName="fooItem1")
fooItem1.setStyleSheet('background: #44ffff')
fooItem2 = QtWidgets.QLabel("fooItem2", objectName="fooItem2")
fooItem2.setStyleSheet('background: #ffff56;')
fooItem3 = QtWidgets.QLabel("fooItem3", objectName="fooItem3")
fooItem3.setStyleSheet('background: #ff42ff;')
fooLayout.addWidget(fooItem1)
fooLayout.addWidget(fooItem2)
fooLayout.addWidget(fooItem3)
scrollLayout.addWidget(fooGroup)
def onFooGroupClick(self, title, obj): # +++
print(f"Group: {title}; objectName=`{obj.objectName()}`")
if __name__ == '__main__':
app = QtWidgets.QApplication([])
window = MainWindow()
window.show()
app.exec_()

How to make window be shown not only once while initing another window's class at the same time? [duplicate]

This question already has answers here:
Variable scopes in Python classes
(4 answers)
Closed 3 years ago.
I am making an addressbook on PyQt5 and can't make the window be shown completely because it is shown only once.
I know that the problem occurs because I am trying to initiate the class when the button is clicked, but it's the only way I've came up with to uptade the QLabel text, otherwise the window will be shown without any text on it.
Here is some code:
from PyQt5 import QtWidgets
class Window(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(400,200)
self.show()
self.text = ''
self.button = QtWidgets.QPushButton('Show')
self.box = QtWidgets.QVBoxLayout()
self.box.addWidget(self.button)
self.setLayout(self.box)
self.button.clicked.connect(self.init)
def init(self):
self.text = 'Text'
win2 = AppearWindow()
win2.show()
class AppearWindow(QtWidgets.QWidget):
def __init__(self):
QtWidgets.QWidget.__init__(self)
self.resize(100, 50)
self.label = QtWidgets.QLabel()
self.label.setText(win.text)
self.box = QtWidgets.QVBoxLayout()
self.box.addWidget(self.label)
self.setLayout(self.box)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
win = Window()
sys.exit(app.exec_())
How can I make AppearWindow be shown if I want the QLabel text on it be updated when the button on the main window is clicked?
Try it:
from PyQt5 import QtWidgets
import random
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.text = ''
self.button = QtWidgets.QPushButton('Show')
self.button.clicked.connect(self.init)
self.box = QtWidgets.QVBoxLayout()
self.box.addWidget(self.button)
self.setLayout(self.box)
def init(self):
self.text = random.choice(['Text1', 'Text2', 'Text3'])
self.win2 = AppearWindow(self.text) # + self
self.win2.show() # + self
class AppearWindow(QtWidgets.QWidget):
def __init__(self, text):
QtWidgets.QWidget.__init__(self)
self.resize(100, 50)
self.label = QtWidgets.QLabel()
# self.label.setText(win.text)
self.label.setText(text)
self.box = QtWidgets.QVBoxLayout()
self.box.addWidget(self.label)
self.setLayout(self.box)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
win = Window()
win.resize(400,200)
win.show()
sys.exit(app.exec_())

How can I get more input text in PyQt5 InputDialog?

I want get more than one input text from user in PyQt5.QtWidgets QInputDialog ... in this code I can just get one input text box and I want get more input text box when I was clicked the button. See the picture to more information ...
from PyQt5.QtWidgets import (QApplication,QWidget,QPushButton,QLineEdit,QInputDialog,QHBoxLayout)
import sys
class FD(QWidget):
def __init__(self):
super().__init__()
self.mysf()
def mysf(self):
hbox = QHBoxLayout()
self.btn = QPushButton('ClickMe',self)
self.btn.clicked.connect(self.sd)
hbox.addWidget(self.btn)
hbox.addStretch(1)
self.le = QLineEdit(self)
hbox.addWidget(self.le)
self.setLayout(hbox)
self.setWindowTitle("InputDialog")
self.setGeometry(300,300,290,150)
self.show()
def sd(self):
text , ok = QInputDialog.getText(self,'InputDialog','EnterYourName = ')
if ok:
self.le.setText(str(text))
if __name__ == '__main__':
app = QApplication(sys.argv)
F = FD()
sys.exit(app.exec_())
QInputDialog is a convenience class to retrieve a single input from the user.
If you want more fields, use a QDialog.
For example:
class InputDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.first = QLineEdit(self)
self.second = QLineEdit(self)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self);
layout = QFormLayout(self)
layout.addRow("First text", self.first)
layout.addRow("Second text", self.second)
layout.addWidget(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def getInputs(self):
return (self.first.text(), self.second.text())
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = InputDialog()
if dialog.exec():
print(dialog.getInputs())
exit(0)
Here's is a general solution, which accepts any number of inputs, based on Dimitry Ernot's answer.
from PyQt5.QtWidgets import QApplication, QLineEdit, QDialogButtonBox, QFormLayout, QDialog
from typing import List
class InputDialog(QDialog):
def __init__(self, labels:List[str], parent=None):
super().__init__(parent)
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, self)
layout = QFormLayout(self)
self.inputs = []
for lab in labels:
self.inputs.append(QLineEdit(self))
layout.addRow(lab, self.inputs[-1])
layout.addWidget(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def getInputs(self):
return tuple(input.text() for input in self.inputs)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
dialog = InputDialog(labels=["First","Second","Third","Fourth"])
if dialog.exec():
print(dialog.getInputs())
exit(0)

Categories