Add dynamic number of QLabel and QLineEdit inside a tab widget - python

I want to make a button that when press, it will generate a label and line edit. I tried using this code but the label will goes to the mainwindow. I want to put that on tabwidget page I create on QT designer.
def predict_student(self):
self.label = QLabel('This is label', self)
self.label.show()

I just solved my problem by creating a form layout inside the page and adding the label on that specific layout.
def predict_student(self):
self.label1 = QLabel('This is label', self)
self.formLayout.addWidget(self.label1)
self.label1.show()

Related

Python PyQt5 I wanna set the position of my Grid Layout

I need to set the position of my Grid Layout. It has to be exactly where I want it to be. I've tried some methods like ".setGeometry, .setAlignment" and I couldn't unfortunately have the result exactly I wanted.
As you can see from this photo, I want it to be in the bottom right but I guess there's no method for it. (I need to say that the interface in the photo below is a different interface. I don't need this interface. Because of I wanted to show you exactly what kind of stuff I wanted.)
You can achieve this using layouts and their setStretch methods.
Here is a runnable example:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class MainWindow(QMainWindow):
def __init__(self, parent=None) -> None:
super().__init__(parent)
self.central = QWidget()
# create a vertical layout and add stretch so it is the first
# item of the layout and everything that is inserted after
# is pushed down to the bottom
self.layout = QVBoxLayout(self.central)
self.layout.addStretch()
self.btn1 = QPushButton("PushButton", self)
self.btn2 = QPushButton("PushButton", self)
self.btn3 = QPushButton("PushButton", self)
# create a horizontal layout and add stretch so everything is
# pushed to the right
self.hlayout = QHBoxLayout()
self.hlayout.addStretch()
# add buttons after the stretch so they will be pushed to the
# right
self.hlayout.addWidget(self.btn1)
self.hlayout.addWidget(self.btn2)
self.hlayout.addWidget(self.btn3)
# add horizontal layout to vertical layout which will be pushed
# to the bottom from the vertical layouts stretch
self.layout.addLayout(self.hlayout)
self.setCentralWidget(self.central)
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
The alternative would be to use the QHBoxLayout.setgeometry(QRect(x, y, w, h)) but this will force the layout into a specific position that will not adjust dynamically if you resize the window, or for any other reason.
This is essentially what is happening in the code above. The blue lines would represent the stretch. the stretch can be thought of as invisible pressure that can be inserted into any layout, before, after, or between any widgets, It can work in either direction.
This same process can be done using QGridWidget.

How to transfer mouse focus back while showing a QMenu?

I have two buttons and both of the has some hovering effect. The first button has a menu as well, and the problem is, when the first button is clicked and menu appears, the mouse hover doesn't work for the second button at the same time until the menu is closed.
I'm not sure, but I believe it is due to some sort of focusPolicy, and I tried to find the solution but I couldn't. I just want to make hovering effect on the buttons of the widget available even while showing the menu.
from PySide2 import QtWidgets, QtGui, QtCore
import sys
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super(MyWidget, self).__init__()
self.resize(300, 300)
layout = QtWidgets.QHBoxLayout(self)
btn = QtWidgets.QPushButton('Button 1')
btn.setStyleSheet('QPushButton::hover{background-color: gray;}')
layout.addWidget(btn)
menu = QtWidgets.QMenu(self)
action = QtWidgets.QAction('buttonAction', menu)
menu.addAction(action)
btn.setMenu(menu)
btn = QtWidgets.QPushButton('Button 2')
btn.setStyleSheet('QPushButton::hover{background-color: gray;}')
layout.addWidget(btn)
self.setLayout(layout)
app = QtWidgets.QApplication([])
wig = MyWidget()
wig.show()
sys.exit(app.exec_())
Please be noted, instead of stylesheet, I even tried using evenFilter changing the colors on Enter/Leave events and returning True/`False values.
TL; DR; The behavior you want is not possible.
Explanation:
Only one window can have the focus and only the widgets that belong to that window can get the focus. In this case, the QMenu lives in a different window that is on top of the original window and that window is the one with the focus and no longer the original window.

ipywidgets use checkbox to display or hide other widgets

I am using ipywidgets to create a short form, showing two fields, the expected width and the height of an image.
I want to add a checkbox so that if the box is checked, the information is loaded from a file instead.
If the box is checked, a text area (or file selector) should appear and a button to load the file read it and fill the text boxes.
Should I do this by observing the checkbox event? is there a way to hide a widget?
I'm not sure there is a hide function for a widget. One way to do this would be to construct an VBox for your widgets, and add the widgets as children. Then create a function/method which reassigns the children of that VBox to which ever widgets you want to show.
from ipywidgets import Checkbox, VBox
cb1 = Checkbox(description='1')
cb2 = Checkbox(description='2')
cb3 = Checkbox(description='3')
vb = VBox(children = [cb1, cb2, cb3])
top_toggle = Checkbox(description='Remove 3')
def remove_3(button):
if button['new']:
vb.children = [cb1, cb2]
else:
vb.children = [cb1, cb2, cb3]
top_toggle.observe(remove_3, names='value')
display(top_toggle)
display(vb)

A scrolling list of widgets without QListWidget

I need to list a bunch of custom widgets in a scrolling area.
I would normally just use QListWidget, but that does not do smooth scrolling, which for me is a necessity. I found this question about smooth scrolling in a QListWidget, but when I try that solution, I get an error saying QListWidget.updateGeometries() requires at least one parameter!
I also thought about using a QScrollArea with multiple widgets in it, but it seems there is no way to do this. If I use a layout, the widgets inside resize. If I set multiple widgets as the child of a QWidget, then put that QWidget as the widget for my QScrollArea (as suggested here), only the last widget I set as a child of my QWidget shows up.
I might well be doing something wrong, as I am not very familiar with widget parenting, so maybe that's my problem. I don't know:
class EditDialog(QDialog):
def __init__(self):
super(EditDialog,self).__init__()
self.scroller = QScrollArea()
self.form = QWidget()
self.form.setStyleSheet()
self.lab = QLabel(self.form)
self.lab.setText("Label")
self.edit = QLineEdit(self.form)
self.edit.setText("LineEdit")
self.but = QPushButton("PushButton",self.form)
self.scroller.setWidget(self.form)
self.layout = QVBoxLayout()
self.layout.addWidget(self.scroller)
self.setLayout(self.layout)
self.setWindowTitle(widget + " - StyleWise")
self.exec_()
With this code, the QListWidget scrolls 100 pixels at a time, but I want it to scroll 1 or 2 at a time. I don't know what to do!

PyQt: getting widgets to resize automatically in a QDialog

I'm having difficulty getting widgets in a QDialog resized automatically when the dialog itself is resized.
In the following program, the textarea resizes automatically if you resize the main window. However, the textarea within the dialog stays the same size when the dialog is resized.
Is there any way of making the textarea in the dialog resize automatically? I've tried using setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) on the dialog itself and the two widgets within, but that seems to have no effect.
I'm using Qt version 3.3.7 and PyQt version 3.5.5-29 on openSuSE 10.2, if that's relevant.
import sys
from qt import *
# The numbers 1 to 1000 as a string.
NUMBERS = ("%d " * 1000) % (tuple(range(1,1001)))
# Add a textarea containing the numbers 1 to 1000 to the given
# QWidget.
def addTextArea(parent, size):
textbox = QTextEdit(parent)
textbox.setReadOnly(True)
textbox.setMinimumSize(QSize(size, size*0.75))
textbox.setText(NUMBERS)
class TestDialog(QDialog):
def __init__(self,parent=None):
QDialog.__init__(self,parent)
self.setCaption("Dialog")
everything = QVBox(self)
addTextArea(everything, 400)
everything.resize(everything.sizeHint())
class TestMainWindow(QMainWindow):
def __init__(self,parent=None):
QMainWindow.__init__(self,parent)
self.setCaption("Main Window")
everything = QVBox(self)
addTextArea(everything, 800)
button = QPushButton("Open dialog", everything)
self.connect(button, SIGNAL('clicked()'), self.openDialog)
self.setCentralWidget(everything)
self.resize(self.sizeHint())
self.dialog = TestDialog(self)
def openDialog(self):
self.dialog.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainwin = TestMainWindow(None)
app.setMainWidget(mainwin)
mainwin.show()
app.exec_loop()
QMainWindow has special behavior for the central widget that a QDialog does not. To achieve the desired behavior you need to create a layout, add the text area to the layout and assign the layout to the dialog.
Just to add a little note about this - I was trying to have a child window spawned from an application, which is a QDialog, containing a single QTextEdit as a child/content - and I wanted the QTextEdit to resize automatically whenever the QDialog window size changes. This seems to have done the trick for me with PyQt4:
def showTextWindow(self):
#QVBox, QHBox # don't exist in Qt4
dialog = QDialog(self)
#dialog.setGeometry(QRect(100, 100, 400, 200))
dialog.setWindowTitle("Title")
dialog.setAttribute(QtCore.Qt.WA_DeleteOnClose)
textbox = QTextEdit(dialog)
textbox.setReadOnly(True)
textbox.setMinimumSize(QSize(400, 400*0.75))
textbox.setText("AHAAA!")
# this seems enough to have the QTextEdit
# autoresize to window size changes of dialog!
layout = QHBoxLayout(dialog)
layout.addWidget(textbox)
dialog.setLayout(layout)
dialog.exec_()
I had looked at using a QLayout before but had no luck. I was trying to do something like
dialog.setLayout(some_layout)
but I couldn't get that approach to work so I gave up.
My mistake was that I was trying to pass the layout to the dialog when I should have been passing the dialog to the layout.
Adding the lines
layout = QVBoxLayout(self)
layout.add(everything)
to the end of TestDialog.__init__ fixes the problem.
Thanks to Monjardin for prompting me to reconsider layouts.
Check out Python QT Automatic Widget Resizer It's suppose to work well.

Categories