QT layout in layout shrinks automatically - qt

I am using Qt Designer to create a main window and I have the following result:
The above opened with PyQt6 using the following code:
from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6 import uic
import sys
class UI(QMainWindow):
def __init__(self):
super().__init__()
uic.loadUi("form.ui", self)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = UI()
window.show()
sys.exit(app.exec())
However, in the Qt designer the actual form looks sth like this:
As you can notice the x, y and z text and line edits look weird and dimensionally different from the Qt Designer.
There I have a layout in layout and for some reason the the inner layout shrinks. Is it actually possible to fix the error in Qt Designer without modifying the code?
Thank you for your attention!
Edit 1:
Outer layout Property - Value pairs:
Inner layout Property - Value pairs:

Related

Draw transparent image over the screen with Qt

I'm trying to draw an image with a transparent background over the entire screen.
I've done similar with Xlib, but I thought I'd try Qt so my program might work in different environments besides X11.
Before getting committed, I've honestly just searched the internet trying to find a working example but failed.
So I've got an image of coordinates that I want to overlay on the screen.
The image is a PNG with a transparent background.
Here's a picture of what I want to see, my desktop with coordinates:
Here's my PyQt6 code, it draws the image fullscreen but sadly you can't see through it, it has a black background:
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QImage
from PyQt6.QtWidgets import QApplication, QMainWindow
from PyQt6.QtGui import QPainter
class Img(QMainWindow):
def __init__(self, img_path, parent=None):
super().__init__(parent)
self.qimg = QImage(img_path)
self.setStyleSheet('QMainWindow {background:transparent}')
self.setWindowFlags(
Qt.WindowType.WindowStaysOnTopHint |
Qt.WindowType.FramelessWindowHint |
Qt.WindowType.WindowTransparentForInput
)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
def paintEvent(self, qpaint_event):
painter = QPainter(self)
rect = qpaint_event.rect()
painter.drawImage(rect, self.qimg)
self.showFullScreen()
if __name__ == "__main__":
app = QApplication(sys.argv)
img_path = 'coords.png'
window = Img(img_path)
window.show()
sys.exit(app.exec())
Answers don't need to be PyQt6, perhaps PyQt5 or written in Go.
I have tried your code and it works fine, apparently it seems to be a problem of the image, I recommend you to use some kind of external application to erase the transparent parts like this.
Here is a test that works with your code:
If you want to do this automatically I recommend you to use opencv.

Qt: HBoxLayout - stop MainWindow from resizing to contents

It seems most people are asking how to make their QMainWindow resize to its contents - I have the opposite problem, my MainWindow does resize and I don't know why.
When I set my QLabel to a longer text, my mainwindow suddenly gets bigger, and I can't find out why that happens.
The following example code basically contains:
A QMainWindow
A QWidget as central widget
A QVBoxLayout as a child of that
A LabelBar inside that.
The LabelBar is a QWidget which in turn contains:
A QHBoxLayout
Two QLabels in that.
After a second, a QTimer sets the label to a longer text to demonstrate the issue.
PyQt example code:
from PyQt5.QtWidgets import (QApplication, QHBoxLayout, QLabel, QWidget,
QMainWindow, QVBoxLayout, QSizePolicy)
from PyQt5.QtCore import QTimer
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
cwidget = QWidget(self)
self.setCentralWidget(cwidget)
self.resize(100, 100)
vbox = QVBoxLayout(cwidget)
vbox.addWidget(QWidget())
self.bar = LabelBar(self)
vbox.addWidget(self.bar)
timer = QTimer(self)
timer.timeout.connect(lambda: self.bar.lbl2.setText("a" * 100))
timer.start(1000)
class LabelBar(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
hbox = QHBoxLayout(self)
self.lbl1 = QLabel(text="eggs")
hbox.addWidget(self.lbl1)
self.lbl2 = QLabel(text="spam")
hbox.addWidget(self.lbl2)
if __name__ == '__main__':
app = QApplication([])
main = MainWindow()
main.show()
app.exec_()
Main window grows because it's the goal of using layouts. Layouts make size requirements for their widgets to ensure that all content is displayed correctly. Requirements depend on child widgets. For example, QLabel by default grows horizontally and require space to fit its content. There are many ways to prevent window growing, and the resulting behavior varies:
You can put QLabel in a QScrollArea. When label's text is too long, scrollbars will appear.
You can enable word wrap using self.lbl2.setWordWrap(True). As long as you set text with some spaces, QLabel will display it in several lines, and window will grow vertically a bit instead of growing horizontally.
You can ignore QLabel's size hint using self.lbl2.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed). QLabel's content will not affect its layout or parent widget size. Too large text will be truncated.

Qt:How to create a Window that does not minimize and do not block background GUI

I have a QMainWindow that is a child to another window. When the user clicks anywhere in the parent window, I do not want the child window to be minimized. The child window should lose the focus and user should be able to continue working on the parent window.
This functionality is similar to the find/replace dialogs found in libreoffice/excel/openoffice etc as shown below. We can see that the task-bar shows only the parent application window and the child window is not visible in task-bar.
Are there any signals on QMainWindow that could help me achieve this? Or what would be the best way to do this?
If you open the new window as Dialog and give it a parent, it should stay on top of the parent. Since you're using QMainWindow, you can pass this with the constructor. If you decide to use QDialog, make sure you make it modeless with setModal(False). Otherwise it will block the parent.
A small example:
import sys
from PyQt4 import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
w = QtGui.QWidget()
layout = QtGui.QVBoxLayout(w)
self.button = QtGui.QPushButton('Open Dialog')
self.text = QtGui.QTextEdit()
layout.addWidget(self.button)
layout.addWidget(self.text)
self.setCentralWidget(w)
self.button.clicked.connect(self.openDialog)
def openDialog(self):
self.dialog = QtGui.QMainWindow(self, QtCore.Qt.Dialog)
self.dialog.show()
app = QtGui.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())

Why won't my dialog show properly when I set its parent on instantiation?

In the attached example script, why won't the MyDialog instance show properly when I set MyDialog's parent to self on line 20 instead of leaving it blank? First I thought the shortcut had stopped working somehow, but obviously that's not the case.
In this case it doesn't really make any difference whether the parent is set, but in my real case I need the parent to be set.
Am I missing something obvious here?
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class MyDialog(QDialog):
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.setWindowFlags(Qt.FramelessWindowHint)
self.setFocusPolicy(Qt.StrongFocus)
label = QLabel(self)
label.setText("World")
hbox = QHBoxLayout()
hbox.addWidget(label)
self.setLayout(hbox)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.my_dialog = MyDialog()
#self.my_dialog = MyDialog(self)
label = QLabel(self)
label.setText("Hello")
self.setCentralWidget(label)
shortcut = QShortcut(QKeySequence(Qt.Key_Tab), self, self.show_my_dialog)
shortcut.setContext(Qt.ApplicationShortcut)
self.show()
def show_my_dialog(self):
md = self.my_dialog
if md.isVisible():
md.hide()
print 'hide'
else:
md.show()
print 'show'
def main():
app = QApplication([])
main_window = MainWindow()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
On my machine (Kubuntu 11.10) it's working.
If Dialog's parent is None - it opens another frameless window, and i have two entries in taskbar. If i close the main window, dialog remains.
If you are using Windows - the behavior you described might be related to it. Maybe the window is shown, it's just behind other windows?
If Dialog's parent is the main window - the frameless dialog is shown inside the main window - in the top left corner near the label.
You might be interested in this info:
A dialog window is a top-level window mostly used for short-term tasks
and brief communications with the user. QDialogs may be modal or
modeless. QDialogs can provide a return value, and they can have
default buttons. QDialogs can also have a QSizeGrip in their
lower-right corner, using setSizeGripEnabled().
Note that QDialog (an
any other widget that has type Qt::Dialog) uses the parent widget
slightly differently from other classes in Qt. A dialog is always a
top-level widget, but if it has a parent, its default location is
centered on top of the parent's top-level widget (if it is not
top-level itself). It will also share the parent's taskbar entry.
Use
the overload of the QWidget::setParent() function to change the
ownership of a QDialog widget. This function allows you to explicitly
set the window flags of the reparented widget; using the overloaded
function will clear the window flags specifying the window-system
properties for the widget (in particular it will reset the Qt::Dialog
flag).

Qt's opaqueresize property on QSplitter meaning

I didn't find this on the web...
What does this opaqueResize property on QSplitter (see doc) stand for?
Thanks.
I am not really sure what you are asking here. It's all in the docs.
QSplitter resizes its children
dynamically by default. If you would
rather have QSplitter resize the
children only at the end of a resize
operation, call setOpaqueResize(false)
Meaning if you set setOpaqueResize(false) on your splitter, start your application and try to pull the splitter to resize the widgets it holds it will not actually resize widgets until you release the splitter. On the other hand if it is set to true it will try to resize the widgets while you are dragging the splitter handle.
It can be useful to turn this feature off if your custom widgets take long time to draw for example since it would make resizing quite slow.
But to answer your question, property opaqueResize holds whether resizing is opaque or not, i.e. will it resize the widgets while dragging the splitter or not.
Example:
Here is a PyQt example you can try (I had example laying around in Python, but it should work the same in C++):
from PyQt4 import QtGui, QtCore
class Example(QtGui.QWidget):
def __init__(self, *args, **kwargs):
super(Example, self).__init__(*args, **kwargs)
top = QtGui.QLabel('test', self)
bottom = QtGui.QPushButton('test', self)
splitter = QtGui.QSplitter(QtCore.Qt.Vertical)
# Try changing from False to True
splitter.setOpaqueResize(False)
splitter.addWidget(top)
splitter.addWidget(bottom)
hbox = QtGui.QHBoxLayout(self)
hbox.addWidget(splitter)
self.setLayout(hbox)
self.setGeometry(250, 200, 350, 250)
def main():
app = QtGui.QApplication([])
ex = Example()
ex.show()
app.exec_()
if __name__ == '__main__':
main()
Hope this makes things a bit clearer.

Resources