Issue
I've created windows form in pyside6. It has a master frame and console frame. There is a spliter to move console frame (Up and Down) and a (toggle) button.
When I click the Toggle button, the console frame show and if I click again , its hide the frame.
this is the design part:
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QFrame, QHBoxLayout, QMainWindow,
QPushButton, QSizePolicy, QSplitter, QTextEdit,
QVBoxLayout, QWidget)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
if not MainWindow.objectName():
MainWindow.setObjectName(u"MainWindow")
MainWindow.setEnabled(True)
MainWindow.resize(1234, 905)
MainWindow.setStyleSheet(u"background-color: rgb(58, 58, 102);")
MainWindow.setUnifiedTitleAndToolBarOnMac(True)
self.centralwidget = QWidget(MainWindow)
self.centralwidget.setObjectName(u"centralwidget")
self.verticalLayout = QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName(u"verticalLayout")
self.splitter = QSplitter(self.centralwidget)
self.splitter.setObjectName(u"splitter")
self.splitter.setMinimumSize(QSize(0, 4))
self.splitter.setStyleSheet(u"")
self.splitter.setOrientation(Qt.Vertical)
self.master_frame = QFrame(self.splitter)
self.master_frame.setObjectName(u"master_frame")
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(1)
sizePolicy.setHeightForWidth(self.master_frame.sizePolicy().hasHeightForWidth())
self.master_frame.setSizePolicy(sizePolicy)
self.master_frame.setMaximumSize(QSize(16777215, 16777215))
self.master_frame.setFrameShape(QFrame.StyledPanel)
self.master_frame.setFrameShadow(QFrame.Raised)
self.horizontalLayout = QHBoxLayout(self.master_frame)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.horizontalLayout.setContentsMargins(0, -1, 0, 0)
self.visual_frame = QFrame(self.master_frame)
self.visual_frame.setObjectName(u"visual_frame")
self.visual_frame.setFrameShape(QFrame.StyledPanel)
self.visual_frame.setFrameShadow(QFrame.Raised)
self.horizontalLayout_2 = QHBoxLayout(self.visual_frame)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.textEdit = QTextEdit(self.visual_frame)
self.textEdit.setObjectName(u"textEdit")
self.textEdit.setStyleSheet(u"background-color: rgb(52, 52, 52); color: rgb(255, 255, 255);")
self.horizontalLayout_2.addWidget(self.textEdit)
self.horizontalLayout.addWidget(self.visual_frame)
self.ctrl_frame = QFrame(self.master_frame)
self.ctrl_frame.setObjectName(u"ctrl_frame")
self.ctrl_frame.setMinimumSize(QSize(250, 0))
self.ctrl_frame.setMaximumSize(QSize(250, 16777215))
self.ctrl_frame.setFrameShape(QFrame.StyledPanel)
self.ctrl_frame.setFrameShadow(QFrame.Raised)
self.btn_toggle = QPushButton(self.ctrl_frame)
self.btn_toggle.setObjectName(u"btn_toggle")
self.btn_toggle.setGeometry(QRect(40, 450, 171, 81))
font = QFont()
font.setPointSize(19)
self.btn_toggle.setFont(font)
self.btn_toggle.setCursor(QCursor(Qt.ArrowCursor))
self.btn_toggle.setStyleSheet(u"color: rgb(255, 255, 255);")
self.horizontalLayout.addWidget(self.ctrl_frame)
self.splitter.addWidget(self.master_frame)
self.console_frame = QFrame(self.splitter)
self.console_frame.setObjectName(u"console_frame")
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.console_frame.sizePolicy().hasHeightForWidth())
self.console_frame.setSizePolicy(sizePolicy1)
self.console_frame.setMinimumSize(QSize(0, 0))
self.console_frame.setMaximumSize(QSize(16777215, 16777215))
self.console_frame.setBaseSize(QSize(0, 0))
self.console_frame.setFrameShape(QFrame.StyledPanel)
self.console_frame.setFrameShadow(QFrame.Raised)
self.verticalLayout_4 = QVBoxLayout(self.console_frame)
self.verticalLayout_4.setObjectName(u"verticalLayout_4")
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.textEdit_console = QTextEdit(self.console_frame)
self.textEdit_console.setObjectName(u"textEdit_console")
self.textEdit_console.setMinimumSize(QSize(0, 0))
font1 = QFont()
font1.setPointSize(12)
self.textEdit_console.setFont(font1)
self.textEdit_console.viewport().setProperty("cursor", QCursor(Qt.IBeamCursor))
self.textEdit_console.setStyleSheet(u"background-color: #282C34; color: rgb(0, 255, 0);")
self.verticalLayout_4.addWidget(self.textEdit_console)
self.splitter.addWidget(self.console_frame)
self.verticalLayout.addWidget(self.splitter)
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Toggle Frame", None))
self.btn_toggle.setText(QCoreApplication.translate("MainWindow", u"Toggle", None))
# retranslateUi
this is the function class:
from PySide6.QtWidgets import QMainWindow
class UIFunctions(QMainWindow):
def __init__(self, ui_main_window):
super(UIFunctions, self).__init__()
self.oldPosition = None
self.ui = ui_main_window
self.ui.setupUi(self)
# Console Resize initial
self.setup_console_resize_button()
def setup_console_resize_button(self):
self.ui.btn_toggle.clicked.connect(self.toggle_console_height)
def toggle_console_height(self):
console_frame = self.ui.console_frame
current_height = console_frame.height()
if current_height == 0:
# If the console is hidden, calculate the new height
new_height = 220
self.ui.master_frame.setMaximumHeight(self.ui.master_frame.maximumHeight() + new_height)
else:
# If the console is visible, set the new height to 0
new_height = 0
self.ui.master_frame.setMaximumHeight(self.ui.master_frame.maximumHeight() - current_height)
# Set the size of the console frame explicitly
console_frame.setMinimumHeight(new_height)
console_frame.setMaximumHeight(new_height)
# Calculate splitter sizes
total_height = self.ui.master_frame.maximumHeight() + self.ui.console_frame.maximumHeight()
master_frame_ratio = self.ui.master_frame.maximumHeight() / total_height
console_frame_ratio = self.ui.console_frame.maximumHeight() / total_height
# Set splitter sizes
self.ui.splitter.setSizes([int(master_frame_ratio * total_height), int(console_frame_ratio * total_height)])
main method :
import sys
import platform
import PySide6
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import (QCoreApplication, QPropertyAnimation, QDate, QDateTime, QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt, QEvent)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, QFont, QFontDatabase, QIcon, QKeySequence,
QLinearGradient, QPalette, QPainter, QPixmap, QRadialGradient)
from PySide6.QtWidgets import *
from PySide6.QtWidgets import QApplication
from ui_design import Ui_MainWindow
from ui_functions import UIFunctions
class MainWindow(UIFunctions):
def __init__(self):
super(MainWindow, self).__init__(Ui_MainWindow())
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
but once if i click the toggle button, then the spliter not working properlly !
can you solve the problem ?
Solution
A splitter can only resize a dimension that coincides with its orientation, and within the widget size limits: its minimum and maximum length. If the splitter is horizontal, it can only resize the widget between its minimumWidth()
and maximumWidth()
, eventually considering its minimumSizeHint()
in case of collapsing (hiding the widget whenever it's too small, or showing it again if there's enough space).
That QSplitter doesn't work anymore because doing setMinimumHeight(new_height)
and setMaximumHeight(new_height)
is like doing setFixedHeight(new_height)
, and a vertical splitter cannot change that height.
Since you're also setting the item sizes of the splitter, you should only set the maximum height of the "console", not the minimum (which is implicitly 0). Also note that you should not set an arbitrary maximum height unless one was previously set (which doesn't seem the case), otherwise you would limit the possibility to expand it after toggling, even if it was previously possible.
You should instead restore the default maximum height (QtWidgets.QWIDGETSIZE_MAX
, 16777215) and properly compute the ratios using the currently suggested height, not the maximum, and based on the current height of the splitter container.
Besides, in reality, all this is quite pointless.
If all you want is to toggle the visibility of a widget, just use the proper function, which is exactly what QSplitter normally does, and is achieved by calling the basic setVisible()
QWidget function, against a negation of the current value of that same property:
def toggle_console_height(self):
self.ui.console_frame.setVisible(
not self.ui.console_frame.isVisible()
)
And remove all the remaining code, which is unnecessary.
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.