I want to be able to move a layout to another layout based on a user input. I have the following code which does not appear to work for me. If I switch lines 31 and 34 so that they operate on the widget rather than the layout then I get the expected behaviour but I am hoping to operate on all widgets within a layout by just moving the layout.
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QHBoxLayout, QLabel, QApplication, QVBoxLayout
class b(QWidget):
def __init__(self, name):
super(b, self).__init__()
self.layout = QVBoxLayout(self)
lbl_1 = QLabel(name)
self.layout.addWidget(lbl_1)
class a(QWidget):
def __init__(self):
super(a, self).__init__()
self.layout = QHBoxLayout(self)
self.widget_1 = b('widget 1')
self.widget_2 = b('widget 2')
self.layout.addWidget(self.widget_1)
self.layout.addWidget(self.widget_2)
self.button_layout = QHBoxLayout()
self.move_layout = QPushButton('Move to other layout')
self.move_layout.clicked.connect(lambda: self.move_button())
self.button_layout.addWidget(self.move_layout)
self.widget = 'widget_2'
self.widget_2.layout.addLayout(self.button_layout)
def move_button(self):
if self.widget == 'widget_2':
self.widget_1.layout.addLayout(self.button_layout)
self.widget = 'widget_1'
else:
self.widget_2.layout.addLayout(self.button_layout)
self.widget = 'widget_2'
print('moved widget to {}'.format(self.widget))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = a()
window.show()
sys.exit(app.exec_())
Edit: to clarify, In the example above, the layout I want to move (self.button_layout) is a child layout of self.widget_2.layout. When I click the pushbutton, I want the self.button_layout to be set as a child layout of self.widget_1.layout. Essentially it will do what the code below does but using addLayout instead of addWidget.
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QHBoxLayout, QLabel, QApplication, QVBoxLayout
class b(QWidget):
def __init__(self, name):
super(b, self).__init__()
self.layout = QVBoxLayout(self)
lbl_1 = QLabel(name)
self.layout.addWidget(lbl_1)
class a(QWidget):
def __init__(self):
super(a, self).__init__()
self.layout = QHBoxLayout(self)
self.widget_1 = b('widget 1')
self.widget_2 = b('widget 2')
self.layout.addWidget(self.widget_1)
self.layout.addWidget(self.widget_2)
self.button_layout = QHBoxLayout()
self.move_layout = QPushButton('Move to other layout')
self.move_layout.clicked.connect(lambda: self.move_button())
self.button_layout.addWidget(self.move_layout)
self.widget = 'widget_2'
self.widget_2.layout.addLayout(self.button_layout)
def move_button(self):
if self.widget == 'widget_2':
self.widget_1.layout.addWidget(self.move_layout)
self.widget = 'widget_1'
else:
self.widget_2.layout.addWidget(self.move_layout)
self.widget = 'widget_2'
print('moved widget to {}'.format(self.widget))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = a()
window.show()
sys.exit(app.exec_())
The problem is that if a layout has a parent then it cannot be changed as the error message indicates:
QLayout::addChildLayout: layout "" already has a parent
One possible solution is to remove the parent:
def move_button(self):
self.button_layout.setParent(None)
if self.widget == "widget_2":
self.widget_1.layout.addLayout(self.button_layout)
self.widget = "widget_1"
else:
self.widget_2.layout.addLayout(self.button_layout)
self.widget = "widget_2"
print("moved widget to {}".format(self.widget))
Another alternative is to place the layout in a QWidget that is the container and that place it in the required layout:
class a(QWidget):
def __init__(self):
super(a, self).__init__()
layout = QHBoxLayout(self)
self.widget_1 = b("widget 1")
self.widget_2 = b("widget 2")
layout.addWidget(self.widget_1)
layout.addWidget(self.widget_2)
self.container = QWidget()
container_layout = QHBoxLayout(self.container)
button = QPushButton("Move to other layout")
button.clicked.connect(self.move_button)
container_layout.addWidget(button)
self.widget = "widget_1"
self.move_button()
def move_button(self):
if self.widget == "widget_2":
self.widget_1.layout.addWidget(self.container)
self.widget = "widget_1"
else:
self.widget_2.layout.addWidget(self.container)
self.widget = "widget_2"
print("moved widget to {}".format(self.widget))
Related
I have two tabs, Tab1, and Tab2. On Tab2, there is a button that when clicked, calls a method that updates the QListView data in the same tab. This works successfully.
When trying to call the same method from another class, it will not work. Below is a minimum reproducible example.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import (
QDesktopWidget,
QVBoxLayout,
QHBoxLayout,
QPushButton,
)
from PyQt5.QtCore import Qt
class App(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('App')
self.resize(1200, 800)
self.center()
self.window = MainWindow(self)
self.setCentralWidget(self.window)
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
layout = QVBoxLayout(self)
# Initialize Tabs
tab_holder = QtWidgets.QTabWidget()
tab1 = Home()
tab2 = SecondTab()
tab_holder.addTab(tab1, "Tab1")
tab_holder.addTab(tab2, 'Tab2')
layout.addWidget(tab_holder)
class Home(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Home, self).__init__(parent)
lay = QVBoxLayout(self)
self.btn_login = QPushButton('Login')
self.btn_login.clicked.connect(self.login)
lay.addWidget(self.btn_login)
#QtCore.pyqtSlot()
def login(self):
print('Hello')
SecondTab.load_info()
class SecondTab(QtWidgets.QWidget):
def __init__(self, parent=None):
super(SecondTab, self).__init__(parent)
lay = QVBoxLayout(self)
# Choice Boxes
layout_choice_boxes = QHBoxLayout()
self.list_of_items = QtWidgets.QListView()
self.model_dist = QtGui.QStandardItemModel(self.list_of_items)
layout_choice_boxes.addWidget(self.list_of_items)
# Load data button.
self.loadData = QPushButton('Load Data')
self.loadData.clicked.connect(self.load_info)
# Add all components to main layout.
lay.addLayout(layout_choice_boxes)
lay.addWidget(self.loadData)
#QtCore.pyqtSlot()
def load_info(self):
for member in ['Item 1', 'Item 2', 'Item 3']:
item = QtGui.QStandardItem(member)
item.setCheckable(True)
item.setEditable(False)
check = Qt.Unchecked
item.setCheckState(check)
self.model_dist.appendRow(item)
self.list_of_items.setModel(self.model_dist)
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
The error is on the line in the class Home() where I try to call the method from the SecondTab() class: SecondTab.load_info()
The load_info() method uses self in the SecondTab class, so I tried passing in the class directly like this: SecondTab.load_info(SecondTab()), however, it did not work.
This is a problem about the basic OOP issues, you have to interact with the instances (the objects) and not the classes (the abstraction). So the solution is that the connection between the objects "tab1" and "tab2":
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
layout = QVBoxLayout(self)
# Initialize Tabs
tab_holder = QtWidgets.QTabWidget()
tab1 = Home()
tab2 = SecondTab()
tab_holder.addTab(tab1, "Tab1")
tab_holder.addTab(tab2, 'Tab2')
layout.addWidget(tab_holder)
tab1.btn_login.clicked.connect(tab2.load_info)
class Home(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Home, self).__init__(parent)
lay = QVBoxLayout(self)
self.btn_login = QPushButton('Login')
lay.addWidget(self.btn_login)
This question already has answers here:
How do I assert the identity of a PyQt5 signal?
(2 answers)
Closed 2 years ago.
I've created a search engine in PyQt5, using the code below:
import sys
from PyQt5.QtWidgets import (
QWidget, QLineEdit, QLabel, QScrollArea, QMainWindow,
QApplication, QHBoxLayout, QVBoxLayout, QSpacerItem, QSizePolicy, QCompleter, QPushButton
)
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
tlist = ['thing1', 'thing2', 'thing3', 'thing4']
class Label(QWidget):
def __init__(self, name):
super(Label, self).__init__()
self.name = name
self.lbl = QLabel(self.name)
self.lbl.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
self.btn = QPushButton("Preview")
self.btn.setMaximumSize(QtCore.QSize(100,100))
self.btn.clicked.connect(self.printsignal)
self.hbox = QHBoxLayout()
self.hbox.addWidget(self.lbl)
self.hbox.addWidget(self.btn)
self.setLayout(self.hbox)
def show(self):
for labels in [self, self.lbl]:
labels.setVisible(True)
def hide(self):
for labels in [self, self.lbl]:
labels.setVisible(False)
def printsignal(self):
print("clicked")
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__()
self.controls = QWidget()
self.controlsLayout = QVBoxLayout()
self.widgets = []
for name in tlist:
item = Label(name)
self.controlsLayout.addWidget(item)
self.widgets.append(item)
spacer = QSpacerItem(1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.controlsLayout.addItem(spacer)
self.controls.setLayout(self.controlsLayout)
self.scroll = QScrollArea()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.controls)
self.searchbar = QLineEdit()
self.searchbar.textChanged.connect(self.update_display)
self.completer = QCompleter(tlist)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.searchbar.setCompleter(self.completer)
container = QWidget()
containerLayout = QVBoxLayout()
containerLayout.addWidget(self.searchbar)
containerLayout.addWidget(self.scroll)
container.setLayout(containerLayout)
self.setCentralWidget(container)
self.setGeometry(600, 100, 800, 600)
self.setWindowTitle('Search Engine')
def update_display(self, text):
for widget in self.widgets:
if text.lower() in widget.name.lower():
widget.show()
else:
widget.hide()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
The problem I have is, all the buttons share the same function and I don't know how to make them have different signals, as they are generated automatically. Basically, if I run the code it will show up like
this:
and when I press any of the buttons, it will print "clicked" (as in printsignal function). What I want is a different function for each button. Is there a way to do that?
Normally you can use self.sender().text() to get text from QButton which generated signal.
But because you create own widget Label with QButton and QLabel and you want text from label so you can get directly self.name
def printsignal(self):
print("clicked", self.name)
eventually self.lbl.text()
def printsignal(self):
print("clicked", self.lbl.text())
Working code.
I removed show(), hide() because you don't need it
import sys
from PyQt5.QtWidgets import (
QWidget, QLineEdit, QLabel, QScrollArea, QMainWindow,
QApplication, QHBoxLayout, QVBoxLayout, QSpacerItem, QSizePolicy, QCompleter, QPushButton
)
from PyQt5 import QtCore
from PyQt5.QtCore import Qt
tlist = ['thing1', 'thing2', 'thing3', 'thing4']
class Label(QWidget):
def __init__(self, name):
super().__init__()
self.name = name
self.lbl = QLabel(self.name)
self.lbl.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
self.btn = QPushButton("Preview")
self.btn.setMaximumSize(QtCore.QSize(100,100))
self.btn.clicked.connect(self.printsignal)
self.hbox = QHBoxLayout()
self.hbox.addWidget(self.lbl)
self.hbox.addWidget(self.btn)
self.setLayout(self.hbox)
def printsignal(self):
print("clicked", self.name)
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__()
self.controls = QWidget()
self.controlsLayout = QVBoxLayout()
self.widgets = []
for name in tlist:
item = Label(name)
self.controlsLayout.addWidget(item)
self.widgets.append(item)
spacer = QSpacerItem(1, 1, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.controlsLayout.addItem(spacer)
self.controls.setLayout(self.controlsLayout)
self.scroll = QScrollArea()
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.scroll.setWidgetResizable(True)
self.scroll.setWidget(self.controls)
self.searchbar = QLineEdit()
self.searchbar.textChanged.connect(self.update_display)
self.completer = QCompleter(tlist)
self.completer.setCaseSensitivity(Qt.CaseInsensitive)
self.searchbar.setCompleter(self.completer)
container = QWidget()
containerLayout = QVBoxLayout()
containerLayout.addWidget(self.searchbar)
containerLayout.addWidget(self.scroll)
container.setLayout(containerLayout)
self.setCentralWidget(container)
self.setGeometry(600, 100, 800, 600)
self.setWindowTitle('Search Engine')
def update_display(self, text):
for widget in self.widgets:
if text.lower() in widget.name.lower():
widget.show()
else:
widget.hide()
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
The project occurs loging in and signing in.
Im trying a transition from registerwindow to mainwindow and when we submit the window is automatically transit to mainwindow. There is only way to do this (at least for me) i have to import two python doc which named mainwindow.py and register.py, they are in same doc by the way.
This is the mainmenu.py
from PyQt5 import QtCore,QtGui,QtWidgets
from window.register import Ui_Form
class Ui_MainWindow(object):
def login(self):
self.window = QtWidgets.QWidget()
self.ui = Ui_Form()
self.ui.setupUi(self.window)
self.window.show()
MainWindow.hide()
and this is register.py
from PyQt5 import QtCore, QtGui, QtWidgets
from window.mainmenu import Ui_MainWindow
import sqlite3
class Ui_Form(object):
def submit(self):
sorgu2 = "Select * From users where nickname = ?"
sorgu = "INSERT INTO users values(?,?)"
self.cursor.execute(sorgu,(self.lineEdit.text(),self.lineEdit.text()))
self.connect.commit()
Form.hide()
self.window2 = QtWidgets.QMainWindow()
self.ui2 = Ui_MainWindow()
self.ui2.setupUi(self.window2)
self.window2.show()
Its supposed to be when i clicked to the button the register window will be hidden and mainmenu window will be show. Same thing for the mainmenu but the direct opposite
I know i am doing circular dependent imports but there is no other way but importing them to each other
If second window will be QDialog then you can hide main window, use exec() for QDialog and main window will wait till you close QDialog, and when it returns to main window then you can show it again.
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton("Show Second Window", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.hide() # hide main window
self.second = SecondWindow()
self.second.exec() # will wait till you close second window
self.show() # show main window again
class SecondWindow(QtWidgets.QDialog): # it has to be dialog
def __init__(self):
super().__init__()
self.button = QtWidgets.QPushButton("Close It", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.close() # go back to main window
app = QtWidgets.QApplication([])
main = MainWindow()
app.exec()
The other popular method is to create two widgets with all contents and replace widgets in one window.
from PyQt5 import QtWidgets
class MainWidget(QtWidgets.QWidget):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.button = QtWidgets.QPushButton("Show Second Window", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.close()
self.parent.set_content("Second")
class SecondWidget(QtWidgets.QWidget):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.button = QtWidgets.QPushButton("Close It", self)
self.button.clicked.connect(self.show_second_window)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
self.show()
def show_second_window(self):
self.close()
self.parent.set_content("Main")
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.layout = QtWidgets.QVBoxLayout(self)
self.set_content("Main")
self.show()
def set_content(self, new_content):
if new_content == "Main":
self.content = MainWidget(self)
self.layout.addWidget(self.content)
elif new_content == "Second":
self.content = SecondWidget(self)
self.layout.addWidget(self.content)
app = QtWidgets.QApplication([])
main = MainWindow()
app.exec()
EDIT: Change window's content using QStackedLayout
from PyQt5 import QtWidgets
class FirstWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Show Second Stack", self)
self.button.clicked.connect(self.change_stack)
layout.addWidget(self.button)
def change_stack(self):
self.parent().stack.setCurrentIndex(1)
class SecondWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
layout = QtWidgets.QVBoxLayout(self)
self.button = QtWidgets.QPushButton("Show First Stack", self)
self.button.clicked.connect(self.change_stack)
layout.addWidget(self.button)
def change_stack(self):
self.parent().stack.setCurrentIndex(0)
class MainWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.stack = QtWidgets.QStackedLayout(self)
self.stack1 = FirstWidget(self)
self.stack2 = SecondWidget(self)
self.stack.addWidget(self.stack1)
self.stack.addWidget(self.stack2)
self.show()
app = QtWidgets.QApplication([])
main = MainWindow()
app.exec()
I am just started to use the PyQt5 and I am trying to update the information of a label, through a button that is inside a subclass (QDialog). When I push the button, the program stop and show the message:
"AttributeError: 'New_Player_Window' object has no attribute 'name_window_label'
The idea is that when the Button is pressed, the Qlabel that by default is "Anonimous" become the Name of the User.
The code is:
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout,
QLineEdit, QLabel, QWidget, QPushButton, QMessageBox, QAction, QMenu,
QDialog
import sys
class General_Window(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(500, 500)
self.move(300, 100)
self.setWindowTitle('Black Jack')
#MENUBAR
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
newAct = QAction('New Player', self)
newAct.triggered.connect(General_Window.new_player)
fileMenu.addAction(newAct)
#LABEL
self.name_window_label = QLabel('Anonimous', self)
self.name_window_label.move(245, 15)
self.show()
def update_window(self, value):
print(str(value))
self.name_window_label.setText(str(value))
def new_player(self):
class New_Player_Window(QDialog, General_Window):
def __init__(self):
super().__init__()
self.initUI()
def create(self):
try:
int(self.money.text()) + 2
except:
QMessageBox.question(self, 'PyQt5 message', "You need to
insert a Number", QMessageBox.Ok , QMessageBox.Ok)
else:
global value
value = self.name.text()
print(value)
self.update_window(value)
def initUI(self):
self.setGeometry(300, 230, 250, 120)
self.setWindowTitle('User Information')
#TEXTBOX1
self.name = QLineEdit(self)
self.name.move(110, 5)
self.name.resize(110,20)
#TEXTBOX2
self.money = QLineEdit(self)
self.money.move(110, 40)
self.money.resize(110,20)
#BUTTON1
self.button = QPushButton('Create', self)
self.button.move(5,80)
self.button.clicked.connect(self.create)
#BUTTON2
self.button2 = QPushButton('Cancel', self)
self.button2.move(120,80)
#LABELNAME
self.name_label = QLabel('SHORT NAME', self)
self.name_label.move(20,10)
#LABELNAME
self.money_label = QLabel('MONEY AVAILABLE', self)
self.money_label.move(10,45)
self.show()
self.exec_()
if __name__=="__main__":
New_Player_Window()
if __name__=="__main__":
app = QApplication(sys.argv)
ag = General_Window()
sys.exit(app.exec_())
You have several errors:
As you point out, General_Window has the name_window_label attribute so it would be expected that New_Player_Window would have it too, but name_window_label is created in initUI but you have overwritten it in the New_Player_Window class so that does not exist that attribute but even if it had it, it would not be the name_window_label of the other window since it is another class that has another object, I recommend reading about OOP and especially about inheritance and composition.
Having an internal class of another class is considered a bad practice (with exceptions such as django) since you are creating the class at every moment spending resources unnecessarily.
This is not an error in itself but is a bad practice, do not use global variables since debugging a global variable is complicated since it has a difficult life cycle that can hide other types of problems.
Finally consider using the appropriate widgets for the user to enter the appropriate data type, for example use QSpinBox for integer values so you avoid unnecessary checking. I also add the recommendation to the use of layouts as I will show in my answer.
Going to the design of the solution, when you create a widget consider it as a black box that receives inputs and generates outputs, if the output is synchronous it uses a method where you can retrieve that information and if it is asynchronous it uses a signal, on the other QDialog side is a class specialized in requesting information so you should not update the information in New_Player_Window but in General_Window for it you must pass the information. QDialog uses exec_() to return if the user accepts or rejects the request but for this you must call accept or reject.
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class New_Player_Window(QtWidgets.QDialog):
def __init__(self):
super().__init__()
self.initUI()
def get_values(self):
return self.name.text(), self.money.value()
def initUI(self):
self.setWindowTitle('User Information')
#TEXTBOX1
self.name = QtWidgets.QLineEdit()
#TEXTBOX2
self.money = QtWidgets.QSpinBox(maximum=2147483647)
#BUTTON1
self.button = QtWidgets.QPushButton('Create')
self.button.clicked.connect(self.accept)
#BUTTON2
self.button2 = QtWidgets.QPushButton('Cancel')
self.button2.clicked.connect(self.reject)
lay = QtWidgets.QVBoxLayout(self)
flay = QtWidgets.QFormLayout()
flay.addRow("SHORT NAME", self.name)
flay.addRow("MONEY AVAILABLE", self.money)
lay.addLayout(flay)
hlay = QtWidgets.QHBoxLayout()
hlay.addWidget(self.button)
hlay.addWidget(self.button2)
lay.addLayout(hlay)
self.setFixedSize(self.sizeHint())
class General_Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('Black Jack')
#MENUBAR
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
newAct = QtWidgets.QAction('New Player', self)
newAct.triggered.connect(self.new_player)
fileMenu.addAction(newAct)
#LABEL
self.name_window_label = QtWidgets.QLabel('Anonimous', alignment=QtCore.Qt.AlignCenter)
widget = QtWidgets.QWidget()
self.setCentralWidget(widget)
lay = QtWidgets.QVBoxLayout(widget)
lay.addWidget(self.name_window_label, alignment=QtCore.Qt.AlignTop)
def update_window(self, value):
self.name_window_label.setText(value)
def new_player(self):
w = New_Player_Window()
if w.exec_() == QtWidgets.QDialog.Accepted:
name, value = w.get_values()
print(name, value)
self.update_window(name)
if __name__=="__main__":
app = QtWidgets.QApplication(sys.argv)
ag = General_Window()
ag.show()
sys.exit(app.exec_())
Try it:
import sys
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout,
QLineEdit, QLabel, QWidget, QPushButton,
QMessageBox, QAction, QMenu, QDialog, QSpinBox)
class General_Window(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.resize(500, 500)
self.move(300, 100)
self.setWindowTitle('Black Jack')
#MENUBAR
menubar = self.menuBar()
fileMenu = menubar.addMenu('File')
newAct = QAction('New Player', self)
newAct.triggered.connect(self.new_player)
fileMenu.addAction(newAct)
#LABEL
self.name_window_label = QLabel('Anonimous', self)
self.name_window_label.move(245, 15)
def update_window(self, value):
print(str(value))
self.name_window_label.setText(str(value))
def new_player(self):
self.newPlayerWindow = New_Player_Window(self)
class New_Player_Window(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.value = 12
self.initUI()
def create(self):
value = "{} - {}".format(self.name.text(), self.value)
print(value)
self.parent.update_window(value)
self.close()
def initUI(self):
self.setGeometry(300, 230, 250, 120)
self.setWindowTitle('User Information')
#TEXTBOX1
self.name = QLineEdit(self)
self.name.move(110, 5)
self.name.resize(110,20)
#TEXTBOX2
self.money = QSpinBox(self) #QLineEdit(self)
self.money.setRange(1, 99)
self.money.setValue(12)
self.money.valueChanged.connect(self.moneyValueChanged)
self.money.move(110, 40)
self.money.resize(110,20)
#BUTTON1
self.button = QPushButton('Create', self)
self.button.move(5,80)
self.button.clicked.connect(self.create)
#BUTTON2
self.button2 = QPushButton('Cancel', self)
self.button2.move(120,80)
#LABELNAME
self.name_label = QLabel('SHORT NAME', self)
self.name_label.move(20,10)
#LABELNAME
self.money_label = QLabel('MONEY AVAILABLE', self)
self.money_label.move(10,45)
self.exec_()
def moneyValueChanged(self, value):
self.value = value
if __name__=="__main__":
app = QApplication(sys.argv)
ag = General_Window()
ag.show()
sys.exit(app.exec_())
How do I alter the following code to make it print whatever is written in line edit widget when 'OK' button is pressed? The current version returns "'Example' object has no attribute 'textbox'" error.
import sys
from PyQt5.QtWidgets import QApplication, QWidget,QPushButton,QLineEdit, QHBoxLayout, QLabel, QVBoxLayout
from PyQt5.QtGui import QIcon
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
label = QLabel('Keyword')
button = QPushButton('OK')
textbox = QLineEdit()
hbox = QHBoxLayout()
hbox.addWidget(label)
hbox.addWidget(textbox)
hbox.addWidget(button)
vbox = QVBoxLayout()
vbox.addLayout(hbox)
vbox.addStretch(1)
button.clicked.connect(self.button_clicked)
self.setLayout(vbox)
self.setGeometry(300, 300, 300, 220)
self.setWindowTitle('Icon')
self.setWindowIcon(QIcon('web.png'))
self.show()
def button_clicked(self):
print(self.textbox.text())
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
`
if you want that a variable can be accessed in all parts of the class as in your case is the button_clicked method you must make it a member of the class for it you must use self when you create it.
class Example(QWidget):
[...]
def initUI(self):
label = QLabel('Keyword')
button = QPushButton('OK')
self.textbox = QLineEdit() # change this line
hbox = QHBoxLayout()
hbox.addWidget(label)
hbox.addWidget(self.textbox) # change this line