can anybody tell me what's wrong in the following simple source code. In the picture below you can see my problem. I want a widget which consists of a menu and a QGLWidget, but the QGLWidget overlaid the menu. If I use QtGui.QWidget instead it works fine. How can I increase the space between these elements?
diagram 1:
code of QGLWidget :
class Profile(QtOpenGL.QGLWidget):
def __init__(self, parent = None):
super(Profile, self).__init__(parent)
def initializeGL(self):
GL.glClearColor(1.0, 1.0 , 1.0, 1.0)
def paintGL(self):
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
code of test widget which works fine:
class TestWidget(QtGui.QWidget):
def __init__(self, parent = None):
super(TestWidget, self).__init__(parent)
editor = QtGui.QTextEdit()
grid = QtGui.QGridLayout()
grid.addWidget(editor, 1,1)
self.setLayout(grid)
code of main widget:
class ProfileDetectWidget(QtGui.QWidget):
def __init__(self, parent = None):
super(ProfileDetectWidget, self).__init__(parent)
self.ogl_widget = Profile()
# self.ogl_widget = TestWidget()
grid = QtGui.QGridLayout()
grid.addWidget(self.ogl_widget, 2,1)
self.createActions()
self.createMenus()
self.setLayout(grid)
self.resize(420,320)
def createActions(self):
self.openAct = QtGui.QAction('Open...', self)
def createMenus(self):
fileMenu = QtGui.QMenu("File", self)
fileMenu.addAction(self.openAct)
menubar = QtGui.QMenuBar(self)
menubar.addMenu(fileMenu)
if __name__ == '__main__':
app = QtGui.QApplication(["PyQt OpenGL"])
widget = ProfileDetectWidget()
widget.show()
app.exec_()
In the code of the main widget I changed
grid = QtGui.QGridLayout()
grid.addWidget(self.ogl_widget, 2,1)
to
space = QtGui.QSpacerItem(0,15)
grid = QtGui.QGridLayout()
grid.addItem(space)
grid.addWidget(self.ogl_widget, 2,1)
and it seems to work.
Related
i am new in PyQt but i have a problem i can't solve. I am trying to get text from second window and set it to field, so when i close second window i can print it form first main window, but my "AnotherWindow" button won't fire event and i really don't know why? Here is code. Can anyone guide me?
Thanks
class AnotherWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(1200, 600)
self.text = "basetext"
self.layoutf = QFormLayout()
self.buttonf = QPushButton("get text")
self.buttonf.clicked.connect(lambda: self.getText)
self.line = QLineEdit()
self.layoutf.addRow(self.buttonf,self.line)
self.widgetf = QWidget()
self.widgetf.setLayout(self.layoutf)
self.setCentralWidget(self.widgetf)
def getText(self):
print(self.line.text)
self.text = self.line.text
self.close()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.w = None # No external window yet.
self.mainLayout = QGridLayout()
self.button = QPushButton("Push for Window")
self.button.clicked.connect(self.show_new_window)
self.button1 = QPushButton("Push ")
self.button1.clicked.connect(self.printFromSecondWindow)
self.mainLayout.addWidget(self.button,0,0)
self.mainLayout.addWidget(self.button1, 0, 1)
self.widget = QWidget()
self.widget.setLayout(self.mainLayout)
self.setCentralWidget(self.widget)
def show_new_window(self):
if self.w is None:
self.w = AnotherWindow()
self.w.show()
else:
self.w.close() # Close window.
self.w = None # Discard reference.
def printFromSecondWindow(self):
print(self.w.text)
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
The problem is with self.buttonf.clicked.connect(...). This call attaches a function to the "clicked" action on the button. The function is called without parameters and the return is simply discarded. In your case, lambda: self.get_text is a function that does nothing but return the address of the self.get_text method. Since get_text doesn't need any additional parameters, you can bind it directly to this slot.
self.buttonf.clicked.connect(self.get_text)
You also have a bug later on where you need to call the text method. With these two changes, the working program is
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.Qt import *
class AnotherWindow(QMainWindow):
def __init__(self):
super().__init__()
self.resize(1200, 600)
self.text = "basetext"
self.layoutf = QFormLayout()
self.buttonf = QPushButton("get text")
self.buttonf.clicked.connect(self.getText)
self.line = QLineEdit()
self.layoutf.addRow(self.buttonf,self.line)
self.widgetf = QWidget()
self.widgetf.setLayout(self.layoutf)
self.setCentralWidget(self.widgetf)
def getText(self):
print("the info", self.line.text())
self.text = self.line.text()
self.close()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.w = None # No external window yet.
self.mainLayout = QGridLayout()
self.button = QPushButton("Push for Window")
self.button.clicked.connect(self.show_new_window)
self.button1 = QPushButton("Push ")
self.button1.clicked.connect(self.printFromSecondWindow)
self.mainLayout.addWidget(self.button,0,0)
self.mainLayout.addWidget(self.button1, 0, 1)
self.widget = QWidget()
self.widget.setLayout(self.mainLayout)
self.setCentralWidget(self.widget)
def show_new_window(self):
if self.w is None:
self.w = AnotherWindow()
self.w.show()
else:
self.w.close() # Close window.
self.w = None # Discard reference.
def printFromSecondWindow(self):
print(self.w.text)
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
Instantiate the second window once in the main window constructor. self.w = AnotherWindow (self)
When creating an instance of the second window, self.w = AnotherWindow (self) - self is passed as a parent, so that when the main window is closed, the second window also closes.
To get text from a QLineEdit widget - apply QString text() const, more https://doc.qt.io/qt-5/qlineedit.html#text-prop
You did not show the method printFromSecondWindow in which, as I understand it, you wanted to show what you intended.
Try it:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.Qt import *
class AnotherWindow(QMainWindow):
def __init__(self, parent=None):
super(AnotherWindow, self).__init__(parent)
self.widgetf = QWidget()
self.setCentralWidget(self.widgetf)
# self.resize(1200, 600)
self.text = "basetext"
self.layoutf = QFormLayout(self.widgetf)
self.buttonf = QPushButton("get text")
# self.buttonf.clicked.connect(lambda: self.getText) # ??? lambda
self.buttonf.clicked.connect(self.getText)
self.line = QLineEdit()
self.layoutf.addRow(self.buttonf,self.line)
def getText(self):
print(self.line.text()) # ! .text()
self.text = self.line.text() # ! .text()
self.close()
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.widget = QWidget()
self.setCentralWidget(self.widget)
# ? self.w = None # No external window yet.
self.button = QPushButton("Push for Window")
self.button.clicked.connect(self.show_new_window)
self.button1 = QPushButton("Push ")
self.button1.clicked.connect(self.printFromSecondWindow)
self.mainLayout = QGridLayout(self.widget)
self.mainLayout.addWidget(self.button, 0, 0)
self.mainLayout.addWidget(self.button1, 0, 1)
self.w = AnotherWindow(self) # +++
def show_new_window(self):
# if self.w is None:
# self.w = AnotherWindow()
self.w.show() # !
# else:
# self.w.close() # Close window.
# self.w = None # Discard reference.
def printFromSecondWindow(self): # +++
print(self.w.text)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
So I'm new to PyQt and I can't seem to quite work out all the kinks. For some reason, whenever I click the "play game" button, the image just doesn't appear. However, it does run the InitUI. Can someone tell me what Im doing wrong? (when It just loaded up the image initially, the image appeared.
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 image - pythonspot.com'
self.initUI()
def initUI(self):
central_widget = QWidget()
self.chess = ChessWidget(central_widget)
self.setCentralWidget(central_widget)
self.setWindowIcon(QIcon('web.png'))
self.resize(900,900)
self.center()
self.setFixedSize(self.size())
self.show()
def toggleMenu(self, state):
if state:
self.statusbar.show()
else:
self.statusbar.hide()
# def closeEvent(self, event):
#
# reply = QMessageBox.question(self, 'Message',
# """Are you sure you want to quit?""", QMessageBox.Yes |
# QMessageBox.No, QMessageBox.No)
#
# if reply == QMessageBox.Yes:
# event.accept()
# else:
# event.ignore()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
class ChessWidget(QFrame):
def __init__(self, parent):
super().__init__(parent)
qbtn = QPushButton('Play Game', self)
qbtn.clicked.connect(lambda: qbtn.close())
qbtn.clicked.connect(lambda: self.initUI())
qbtn.resize(qbtn.sizeHint())
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(qbtn)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
def initUI(self):
print("hi")
pixmap = QPixmap("ChessBoard.jpg")
lbl = QLabel(self)
pixmap2 = pixmap.scaledToWidth(900)
hbox = QHBoxLayout(self)
hbox.addStretch(1)
hbox.addWidget(lbl)
lbl.setPixmap(pixmap2) ` if __name__ == '__main__':
app = QApplication([])
ex = Example()
sys.exit(app.exec_()) `
You should be getting a useful warning from Qt; if not, check that your test environment has a console active. The warning is:
QLayout: Attempting to add QLayout "" to ChessWidget "", which already has a layout
This happens when you create the QHBoxLayout in ChessWidget.initUI and try to parent it to the ChessWidget. You have already set a QVBoxLayout on that widget.
A quick solution is to retain the name of your layout (vbox -> self.vbox), then in a click event remove the QPushButton from the layout and add the ChessWidget.
I understand you're just making small tests for learning purposes, but this design pattern with the QPushButton being permanently replaced might not be what you want. If you want the QPushButton and ChessWidget to occupy the same space, look at QStackedWidget. This will allow you to switch from one widget to the other as often as you like. This could be a useful approach if you want to hide the ChessWidget later when no game is active, for example.
Note that when you create your QPushButton and QLabel, it's unnecessary to parent them to the ChessWidget as they will be reparented to the layout when added.
Try it:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
central_widget = QWidget()
self.chess = ChessWidget(central_widget)
self.setCentralWidget(central_widget)
self.layV = QVBoxLayout(central_widget) # +++
self.layV.addWidget(self.chess) # +++
self.setWindowIcon(QIcon('D:/_Qt/img/py-qt.png')) # web.png
self.resize(440,440) #(900,900)
class ChessWidget(QFrame):
def __init__(self, parent=None):
super().__init__(parent)
qbtn = QPushButton('Play Game', self)
qbtn.clicked.connect(lambda: qbtn.close())
qbtn.clicked.connect(lambda: self.initUI())
self.hbox = QHBoxLayout()
self.hbox.addWidget(qbtn)
self.vbox = QVBoxLayout()
self.vbox.addStretch(1)
self.vbox.addLayout(self.hbox)
self.setLayout(self.vbox)
def initUI(self):
print("hi")
pixmap = QPixmap("D:/_Qt/img/pyqt.jpg") # ChessBoard.jpg
lbl = QLabel(self)
self.vbox.addWidget(lbl)
lbl.setPixmap(pixmap.scaled(400, 400, Qt.KeepAspectRatio)) # +++
if __name__ == '__main__':
app = QApplication([])
ex = Example()
ex.setWindowTitle('PyQt5 image - pythonspot.com')
ex.show()
sys.exit(app.exec_())
I am trying to create a window with a scroll area with widgets. This works. I tried to add a simple filter function to this window. This also works. The only problem is that the widgets inside the scroll area don't keep their size, when some are hidden. Is there a way to make sure the widgets in the scroll area maintain their size?
from PyQt5 import QtWidgets, QtCore, QtGui
import sys
# ----------------------------------------------------------------------------
class test(QtWidgets.QDialog):
def __init__(self, *args, **kwargs):
super(test, self).__init__(*args, **kwargs)
self.main_layout = QtWidgets.QVBoxLayout(self)
self.label_widget = QtWidgets.QWidget()
self.label_layout = QtWidgets.QHBoxLayout()
self.label_widget.setLayout(self.label_layout)
self.main_layout.addWidget(self.label_widget)
self.filter_field = QtWidgets.QLineEdit()
self.label_layout.addWidget(self.filter_field)
self.refresh_pbutton = QtWidgets.QPushButton("Refresh")
self.label_layout.addWidget(self.refresh_pbutton)
self.scroll_area = QtWidgets.QScrollArea()
self.main_layout.addWidget(self.scroll_area)
self.refresh_pbutton.clicked.connect(self.refresh)
self.filter_field.textChanged.connect(self.filter)
self.populate()
# ----------------------------------------------------------------------------
def populate(self, *args, **kwargs):
self.widgets = []
self.scroll_widget = QtWidgets.QWidget()
self.scroll_widget.setAutoFillBackground(True)
self.scroll_widget.setStyleSheet("background-color:red;")
self.scroll_layout = QtWidgets.QVBoxLayout()
self.scroll_widget.setLayout(self.scroll_layout)
for i in range(1, 11):
widget = smallWidget(str(i))
self.widgets.append(widget)
self.scroll_layout.addWidget(widget)
self.scroll_area.setWidget(self.scroll_widget)
self.filter_field.setText("")
def refresh(self):
self.populate()
def filter(self):
filter_text = str(self.filter_field.text())
for widget in self.widgets:
if filter_text in widget.name:
widget.show()
else:
widget.hide()
class smallWidget(QtWidgets.QWidget):
def __init__(self, name, *args, **kwargs):
super(smallWidget, self).__init__(*args, **kwargs)
self.name = name
self.main_layout = QtWidgets.QVBoxLayout(self)
self.name_label = QtWidgets.QLabel(self.name)
self.main_layout.addWidget(self.name_label)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
a = test()
a.show()
sys.exit(app.exec_())
You should not add the widgets directly to scroll_layout but create another layout, and in that layout add the widgets and use addStretch() so that it does not occupy the height of the first layout but the necessary one.
def populate(self):
self.widgets = []
self.scroll_widget = QtWidgets.QWidget()
self.scroll_widget.setAutoFillBackground(True)
self.scroll_widget.setStyleSheet("background-color:red;")
self.scroll_layout = QtWidgets.QVBoxLayout()
self.scroll_widget.setLayout(self.scroll_layout)
lay = QtWidgets.QVBoxLayout() # <---
self.scroll_layout.addLayout(lay) # <---
self.scroll_layout.addStretch() # <---
for i in range(1, 11):
widget = smallWidget(str(i))
self.widgets.append(widget)
lay.addWidget(widget) # <---
self.scroll_area.setWidget(self.scroll_widget)
Update:
If you want the size of scroll_widget to be adjusted you must call adjustSize() an instant later with a QTimer since the geometry changes are not applied instantly
def filter(self, text):
for widget in self.widgets:
widget.setVisible(text in widget.name)
QtCore.QTimer.singleShot(0, self.scroll_widget.adjustSize)
I got the following Test-GUI.
There is a left layout and a right layout where i want to put buttons and other things onto. The button on the right should make a QFrame unhide or hide and all the widgets in it. This works.
But after the first two clicks, the layout is different.
The TableWidget on the left layout gets resized and the button is a bit more south.
Is there an easy way to fix this?
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main_widget = MainWidget()
self.setCentralWidget(self.main_widget)
self.show()
class MainWidget(QWidget):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.tab_widget = TabWidget()
self.debugger = Dialog()
self.layout.addWidget(self.tab_widget)
self.layout.addWidget(self.debugger)
self.setLayout(self.layout)
class TabWidget(QTabWidget):
def __init__(self):
super().__init__()
self.tab1 = Tab_1()
self.addTab(self.tab1, "Tab1")
class Tab_1(QWidget):
def __init__(self):
super().__init__()
# LEFT LAYOUT BEGIN
self.table = QTableWidget()
self.table.setRowCount(1)
self.table.setColumnCount(2)
self.table.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.table.resizeColumnsToContents()
left_hlayout = QHBoxLayout()
left_hlayout.addWidget(self.table)
# # LEFT LAYOUT END
#
# # RIGHT LAYOUT BEGIN
self.button_options = QPushButton('Options')
self.button_options.setCheckable(True)
self.button_options.toggled.connect(self.option_pressed)
right_vlayout = QVBoxLayout()
right_vlayout.addWidget(self.button_options)
# # RIGHT LAYOUT END
# MAIN LAYOUT BEGING
self.main_layout = QVBoxLayout()
self.horizontal_layout = QHBoxLayout()
self.horizontal_layout.addLayout(left_hlayout)
self.horizontal_layout.addLayout(right_vlayout)
self.main_layout.addLayout(self.horizontal_layout)
self.option = Options()
self.main_layout.addWidget(self.option)
self.setLayout(self.main_layout)
# MAIN LAYOUT END
def option_pressed(self):
if self.button_options.isChecked():
self.option.setVisible(True)
else:
self.option.setVisible(False)
class Options(QFrame):
def __init__(self):
super().__init__()
self.hide()
self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
self.options_layout = QFormLayout()
self.options_label = QLabel('One')
self.options_lineedit = QLineEdit('Two')
self.options_layout.addRow(self.options_label, self.options_lineedit)
self.setLayout(self.options_layout)
class Dialog(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedHeight(100)
pal = QPalette()
bgc = QColor(210, 210, 210)
pal.setColor(QPalette.Base, bgc)
self.setPalette(pal)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
I am trying to achieve something like this in PySide: https://codepen.io/imprakash/pen/GgNMXO
What I want to do is create a child window frameless with a black overlay below.
I didn't succeed to create a child window frameless and the overlay...
This is a base code to replicate the HTML:
from PySide import QtCore, QtGui
import sys
class MainWindow(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.resize(800, 500)
self.button = QtGui.QPushButton("Click Me")
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(self.button)
# Connections
self.button.clicked.connect(self.displayOverlay)
def displayOverlay(self):
popup = QtGui.QDialog(self)
popup.setWindowFlags(QtCore.Qt.FramelessWindowHint)
popup.setLayout(QtGui.QHBoxLayout())
popup.layout().addWidget(QtGui.QLabel("HI"))
popup.show()
print "clicked"
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
If you comment the line with the FramelessWindowHint, the window comes, else nothing happen...
I really hope that someone could help me. Thank you for the time you spent to read my question.
I'll be using PyQt5 for this explanation. It might have some differences to PySide (which I'm not sure if its still maintained) and PyQt4, but it shouldn't be too hard to convert.
The following example has a parent widget which a few buttons. One of them (the obvious one) calls for the popup. I've prepared the example to deal with the parent resize but have not made any code regarding mouse events of dragging the popup (see mouseMoveEvent and mouseReleaseEvent for that).
So here is the code:
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
class TranslucentWidgetSignals(QtCore.QObject):
# SIGNALS
CLOSE = QtCore.pyqtSignal()
class TranslucentWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(TranslucentWidget, self).__init__(parent)
# make the window frameless
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.fillColor = QtGui.QColor(30, 30, 30, 120)
self.penColor = QtGui.QColor("#333333")
self.popup_fillColor = QtGui.QColor(240, 240, 240, 255)
self.popup_penColor = QtGui.QColor(200, 200, 200, 255)
self.close_btn = QtWidgets.QPushButton(self)
self.close_btn.setText("x")
font = QtGui.QFont()
font.setPixelSize(18)
font.setBold(True)
self.close_btn.setFont(font)
self.close_btn.setStyleSheet("background-color: rgb(0, 0, 0, 0)")
self.close_btn.setFixedSize(30, 30)
self.close_btn.clicked.connect(self._onclose)
self.SIGNALS = TranslucentWidgetSignals()
def resizeEvent(self, event):
s = self.size()
popup_width = 300
popup_height = 120
ow = int(s.width() / 2 - popup_width / 2)
oh = int(s.height() / 2 - popup_height / 2)
self.close_btn.move(ow + 265, oh + 5)
def paintEvent(self, event):
# This method is, in practice, drawing the contents of
# your window.
# get current window size
s = self.size()
qp = QtGui.QPainter()
qp.begin(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
qp.setPen(self.penColor)
qp.setBrush(self.fillColor)
qp.drawRect(0, 0, s.width(), s.height())
# drawpopup
qp.setPen(self.popup_penColor)
qp.setBrush(self.popup_fillColor)
popup_width = 300
popup_height = 120
ow = int(s.width()/2-popup_width/2)
oh = int(s.height()/2-popup_height/2)
qp.drawRoundedRect(ow, oh, popup_width, popup_height, 5, 5)
font = QtGui.QFont()
font.setPixelSize(18)
font.setBold(True)
qp.setFont(font)
qp.setPen(QtGui.QColor(70, 70, 70))
tolw, tolh = 80, -5
qp.drawText(ow + int(popup_width/2) - tolw, oh + int(popup_height/2) - tolh, "Yep, I'm a pop up.")
qp.end()
def _onclose(self):
print("Close")
self.SIGNALS.CLOSE.emit()
class ParentWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(ParentWidget, self).__init__(parent)
self._popup = QtWidgets.QPushButton("Gimme Popup!!!")
self._popup.setFixedSize(150, 40)
self._popup.clicked.connect(self._onpopup)
self._other1 = QtWidgets.QPushButton("A button")
self._other2 = QtWidgets.QPushButton("A button")
self._other3 = QtWidgets.QPushButton("A button")
self._other4 = QtWidgets.QPushButton("A button")
hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(self._popup)
hbox.addWidget(self._other1)
hbox.addWidget(self._other2)
hbox.addWidget(self._other3)
hbox.addWidget(self._other4)
self.setLayout(hbox)
self._popframe = None
self._popflag = False
def resizeEvent(self, event):
if self._popflag:
self._popframe.move(0, 0)
self._popframe.resize(self.width(), self.height())
def _onpopup(self):
self._popframe = TranslucentWidget(self)
self._popframe.move(0, 0)
self._popframe.resize(self.width(), self.height())
self._popframe.SIGNALS.CLOSE.connect(self._closepopup)
self._popflag = True
self._popframe.show()
def _closepopup(self):
self._popframe.close()
self._popflag = False
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
main = ParentWidget()
main.resize(500, 500)
main.show()
sys.exit(app.exec_())
Which results in the following:
The logic is the following. You create an empty Widget and manually draw the background and popup (paintEvent). You add a button for closing the popup. For this you build a Signal and let the parent widget do the closing. This is important because you need to make the parent widget control some important elements of the popup (such as closing, resizng, etc.). You can add far more complexity but hopefully the example will suffice for starters.
Thanks to armatita, I succeed to get what I wanted. For now, there are some issues but it works and I get the result that I wanted.
I give you the code to the next who will be looking for the same thing.
from PySide import QtCore, QtGui
import sys
class CtmWidget(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.button = QtGui.QPushButton("Close Overlay")
self.setLayout(QtGui.QHBoxLayout())
self.layout().addWidget(self.button)
self.button.clicked.connect(self.hideOverlay)
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
path = QtGui.QPainterPath()
path.addRoundedRect(QtCore.QRectF(self.rect()), 10, 10)
mask = QtGui.QRegion(path.toFillPolygon().toPolygon())
pen = QtGui.QPen(QtCore.Qt.white, 1)
painter.setPen(pen)
painter.fillPath(path, QtCore.Qt.white)
painter.drawPath(path)
painter.end()
def hideOverlay(self):
self.parent().hide()
class Overlay(QtGui.QWidget):
def __init__(self, parent, widget):
QtGui.QWidget.__init__(self, parent)
palette = QtGui.QPalette(self.palette())
palette.setColor(palette.Background, QtCore.Qt.transparent)
self.setPalette(palette)
self.widget = widget
self.widget.setParent(self)
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.fillRect(event.rect(), QtGui.QBrush(QtGui.QColor(0, 0, 0, 127)))
painter.end()
def resizeEvent(self, event):
position_x = (self.frameGeometry().width()-self.widget.frameGeometry().width())/2
position_y = (self.frameGeometry().height()-self.widget.frameGeometry().height())/2
self.widget.move(position_x, position_y)
event.accept()
class MainWindow(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.resize(800, 500)
self.button = QtGui.QPushButton("Click Me")
self.setLayout(QtGui.QVBoxLayout())
self.layout().addWidget(self.button)
self.popup = Overlay(self, CtmWidget())
self.popup.hide()
# Connections
self.button.clicked.connect(self.displayOverlay)
def displayOverlay(self):
self.popup.show()
print "clicked"
def resizeEvent(self, event):
self.popup.resize(event.size())
event.accept()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
Once again thank you both of you(ymmx and armatita) to spend time on my issue.
did you try replacing popup.show() by popup.exec_()? and remove self as a parameter of the Qdialog? I change QDialog to QmessageBox to be able to quit the subwindow but it still work with the QDialog.
popup = QMessageBox()
popup.setWindowFlags( Qt.FramelessWindowHint)
popup.setLayout( QHBoxLayout())
popup.layout().addWidget( QLabel("HI"))
popup.exec_()
update
class Popup(QDialog ):
def __init__(self):
super().__init__()
self.setWindowFlags( Qt.CustomizeWindowHint)
self.setLayout( QHBoxLayout())
Button_close = QPushButton('close')
self.layout().addWidget( QLabel("HI"))
self.layout().addWidget( Button_close)
Button_close.clicked.connect( self.close )
self.exec_()
print("clicked")
def mousePressEvent(self, event):
self.oldPos = event.globalPos()
def mouseMoveEvent(self, event):
delta = QPoint (event.globalPos() - self.oldPos)
#print(delta)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.oldPos = event.globalPos()
class MainWindow( QWidget):
def __init__(self):
QWidget.__init__(self)
self.resize(800, 500)
self.button = QPushButton("Click Me")
self.setLayout( QVBoxLayout())
self.layout().addWidget(self.button)
# Connections
self.button.clicked.connect(self.displayOverlay)
def displayOverlay(self):
Popup( )
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())