Skip to content
  • 0 Votes
    6 Posts
    703 Views
    M

    @vinaygopal
    Sorry I know nothing about QML.

  • 0 Votes
    3 Posts
    3k Views
    A

    @nagesh No style sheet, however, I had experiemented with the stylesheet in the link that you sent, and I couldn't figure it out. Which fields pertain to the width of the drop-down?

    There is a horizontal layout, however, I have also tried without layout and I get the same issue.
    I can control the width of the Combobox when it is closed, but once open there is an offset, that is what I would like to remove.

    Thank you,
    Arjun

  • 0 Votes
    1 Posts
    457 Views
    No one has replied
  • 0 Votes
    2 Posts
    1k Views
    V

    It's a QT bug ( https://bugreports.qt.io/browse/QTBUG-79254 )

    If somebody every needs it again I implemented a workaround which I posted here:
    https://stackoverflow.com/questions/62152845/touch-freeze-in-qtwebengine-after-opening-a-dropdown-menu

  • 0 Votes
    3 Posts
    15k Views
    P

    I figured it out finally, some things around OOP are still very confusing for me, I guess I need time and more experience to settle all down. Below is a functional example of simple window with two QToolButtons - a regular one and modified one.

    @JonB: I think that there is no difference between using PyQt and PySide, except for import statements, and loading ui, I think that PyQt cannot load ui file directly, it must be converted to py, maybe I'm wrong.

    Now there are four things that bother me:

    how to use regular QtToolButton as a classic button with drop-down menu (see my example), it seems that triggered signal is always called. Is it designed to work that way? If I don't add signal in code than button does nothing? are there any major flaws in my example that should be corrected/fixed? how to "inject" my custom made object into ui at wanted location? In my example I just inserted it inside grid_layout. Can I make a placeholder somehow? Let's say I have a more complicated window with many widgets, for example:

    window.jpg

    and I want to replace that Add Something button with custom one. What would be the best procedure to do this?
    4) is calling GUI directly from a ui XML file smart thing to do or it would be better to convert it to py first?

    My example, program.py, and form.ui:

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Docs """ import os, sys from PySide2 import QtWidgets, QtUiTools class CustomToolButton(QtWidgets.QToolButton): ''' CustomToolButton description ''' def __init__(self, parent=None): ''' Constructor ''' super(CustomToolButton, self).__init__(parent) self.setPopupMode(self.MenuButtonPopup) self.triggered.connect(self.setDefaultAction) return None class Program(QtWidgets.QWidget): ''' Program description ''' def __init__(self, parent=None): ''' Constructor ''' super(Program, self).__init__(parent) self.program_path = os.path.dirname(os.path.realpath(__file__)) self.loader = QtUiTools.QUiLoader() ui_file_path = os.path.join(self.program_path, 'form.ui') self.window = self.loader.load(ui_file_path, parent) self.setup_ui(self.window) return None def setup_ui(self, window): self.grid_layout = window.gridLayout # tool button created in Qt Designer self.tool_btn = window.toolButton ### THIS RUNS EVERY TIME BUTTON IS CLICKED NO MATTER ### WHAT ACTION YOU CHOOSE FROM DROP-DOWN MENU ### IT SEEMS THAT IN THIS CASE YOU CANNOT USE BUTTON LIKE ### CLASSIC BUTTON, ### THEREFORE IT SEEMS THAT "setDefaultAction" MAKES NO SENSE self.tool_btn.triggered.connect(self.clicked_tool_btn) # custom tool button self.custom_tool_btn = CustomToolButton() self.custom_tool_btn.setText('Custom button') self.custom_tool_btn.setMinimumSize(150,50) self.custom_tool_btn.setMaximumSize(150,50) self.grid_layout.addWidget(self.custom_tool_btn) self.define_ui_elements() def define_ui_elements(self): # tool button created in Qt Designer tool_btn_menu = QtWidgets.QMenu(self) tool_btn_menu.addAction('Action 1', self.action1_activated) tool_btn_menu.addAction('Action 2', self.action2_activated) tool_btn_menu.addAction('Action 3', self.action3_activated) tool_btn_default_action = QtWidgets.QAction('Action 1',self) self.tool_btn.setMenu(tool_btn_menu) self.tool_btn.setDefaultAction(tool_btn_default_action) # custom tool button ''' 1) creating actions ''' action1 = QtWidgets.QAction('Action 1', self) action2 = QtWidgets.QAction('Action 2', self) action3 = QtWidgets.QAction('Action 3', self) ''' 2) creating connections ''' action1.triggered.connect(self.action1_activated) action2.triggered.connect(self.action2_activated) action3.triggered.connect(self.action3_activated) ''' 3) creating btn menu ''' custom_tool_btn_menu = QtWidgets.QMenu(self) custom_tool_btn_menu.addAction(action1) custom_tool_btn_menu.addAction(action2) custom_tool_btn_menu.addAction(action3) ''' 4) setting up menu and default action ''' self.custom_tool_btn.setMenu(custom_tool_btn_menu) self.custom_tool_btn.setDefaultAction(action1) ### THIS RUNS EVERY TIME BUTTON IS CLICKED NO MATTER WHAT ACTION YOU CHOOSE FROM DROP-DOWN MENU def clicked_tool_btn(self): # calling action1_activated() because it is default option self.action1_activated() print('Qt Designer button is clicked.') def action1_activated(self): print('Action 1 activated.') def action2_activated(self): print('Action 2 activated.') def action3_activated(self): print('Action 3 activated.') if __name__ == '__main__': program = QtWidgets.QApplication(sys.argv) main_window = Program() main_window.window.show() sys.exit(program.exec_()) <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Form</class> <widget class="QWidget" name="Form"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>400</width> <height>300</height> </rect> </property> <property name="sizePolicy"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> <width>400</width> <height>300</height> </size> </property> <property name="maximumSize"> <size> <width>400</width> <height>300</height> </size> </property> <property name="windowTitle"> <string>Form</string> </property> <layout class="QGridLayout" name="gridLayout"> <item row="1" column="0"> <widget class="QToolButton" name="toolButton"> <property name="minimumSize"> <size> <width>150</width> <height>50</height> </size> </property> <property name="maximumSize"> <size> <width>150</width> <height>50</height> </size> </property> <property name="text"> <string>QtDsgnrBtn</string> </property> <property name="popupMode"> <enum>QToolButton::MenuButtonPopup</enum> </property> </widget> </item> </layout> </widget> <resources/> <connections/> </ui>
  • Advanced drop-down menu

    Unsolved General and Desktop
    8
    0 Votes
    8 Posts
    5k Views
    J

    That's how I would do it.
    As for the position, have a look at these:

    QMenu::exec(somewidget.mapToGlobal(QPoint(0, 0))); QMenu::popup(somewidget.mapToGlobal(QPoint(0, 0)));
  • 0 Votes
    5 Posts
    5k Views
    S

    @VRonin

    With the provided code the whole dropdown list will be invisible. Do you know how to keep the items unaffected?

  • 0 Votes
    4 Posts
    5k Views
    DongD

    Finally, I made it !!!

    1. To implement "Drop Down List" just like Normal Combo

    "Drop Down List" need to be on top of all other control "Drop Down List" must be disappear when click outside it

    To do that, I need to set the "Root Item" (ApplicationWindow or other Component) as parent of maskMouseArea & recDropDown
    (There is a little tricky here and I write a javascript function to return the "Root Item" & "Referred Coordinate" to the Combo - You need this to display the popup by set x, y position)

    function getRootComponent(component) { var result = {Component : component, refX : 0, refY : 0 } while (result.Component.parent) { result.refX = result.refX + result.Component.x result.refY = result.refY + result.Component.y result.Component = result.Component.parent } return result; }

    When user Click on maskMouseArea it'll close the recDropDown

    Bellow is source code of MyComboBox.qml

    (Note CommonScript.jsBinding is my function to support binding with Dynamic Property, you can use normal binding)

    import QtQuick 2.2 import QtQuick.Controls 1.2 import QtQuick.Controls.Private 1.0 import QtQuick.Controls.Styles 1.2 import "../" import "../commonScripts.js" as CommonScript Rectangle { id: root width: 160 height: MDStyle.comboBoxHeight border.width: 1 border.color: MDStyle.borderColor color: MDStyle.backGroundColor radius: 2 clip: true signal activated(int index) property int currentIndex: -1 property var selectedValue property var selectedItem property string displayMember: "Text" property string valueMember: "Value" property string imageSourceMember: "ImageSource" property bool showIcon: false property int dropDownMinWidth: root.width property int dropDownMaxWidth: 2 * dropDownMinWidth property int maxRowsCount: 6 property var model property bool popupVisible : false property int rowHeight : 28 property string displayText: "" Item { id: privateProperties property var rootAncestor: CommonScript.getRootComponent(root) property int popupWidth : root.dropDownMinWidth property bool popupWidthAutoAdjusted: false } property Component displayItem: Label { id : lblDisplayText anchors.left: parent.left anchors.leftMargin: MDStyle.textFontSize / 2 anchors.right: parent.right anchors.rightMargin: recArrowContainer.width + 2 anchors.verticalCenter: parent.verticalCenter font.family: MDStyle.fontFamily font.pixelSize: MDStyle.textFontSize color: MDStyle.fontColor clip: true text: displayText != "" ? displayText : listItems.selectedIndex >= 0 ? listItems.model[listItems.selectedIndex].binding(displayMember) : "" } Rectangle { id: recControlHover anchors.fill: parent anchors.margins: 2 border.width: 0 color: "#113399FF" visible: clickableArea.containsMouse } //MouseArea to show popup when clicked MouseArea { id: clickableArea anchors.fill: parent hoverEnabled: true onClicked: { root.popupVisible = true return true; } } //Loader for Display Item Loader { id : displayItemLoader anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter sourceComponent: displayItem } //Arrow Image Rectangle { id: recArrowContainer height: parent.height - 2 * anchors.margins width: height - 2 * anchors.margins anchors.top: parent.top anchors.right: parent.right anchors.margins: 1 radius: 2 color: "transparent" Image { id: imgArrow anchors.centerIn: parent width: sourceSize.width height: sourceSize.height source: "qrc:/Images/GUI/metrixa-icon-down-arrow.png" } } //Mask Mouse Area (used to hide Drop Down List when click outside Drop Down List) MouseArea { id: maskMouseArea parent: privateProperties.rootAncestor.Component anchors.fill: parent visible: root.popupVisible onClicked: { root.popupVisible = false return false } z: 9998 } //Drop Down List Rectangle { id: recDropDown parent: privateProperties.rootAncestor.Component width: { return CommonScript.max(root.width, privateProperties.popupWidth + listItems.anchors.leftMargin + listItems.anchors.rightMargin + ddlScrollView.anchors.leftMargin + ddlScrollView.anchors.rightMargin) } height: root.rowHeight * CommonScript.min(root.maxRowsCount, (root.model ? root.model.length : 0)) + ddlScrollView.anchors.topMargin + ddlScrollView.anchors.bottomMargin + listItems.anchors.topMargin + listItems.anchors.bottomMargin clip: true radius:2 x: privateProperties.rootAncestor.refX y: privateProperties.rootAncestor.refY + root.height + 1 border.width: 1 border.color: MDStyle.borderColor color: "#FFFFFF" visible: root.popupVisible z: 9999 ScrollView { id: ddlScrollView anchors.fill: parent anchors.margins: 1 clip: true ListView { id: listItems anchors.left : parent.left anchors.right : parent.right anchors.top : parent.top orientation: Qt.Vertical anchors.margins: 2 height: { //Only count displayed items var visibleItemsCount = 0 for (var i = 0; i < listItems.model.length; i++) { var isVisible = true; if (listItems.model[i].binding("Visible") !== undefined) visible = listItems.model[i].binding("Visible"); if (isVisible) visibleItemsCount = visibleItemsCount + 1 } return CommonScript.min(maxRowsCount, visibleItemsCount) * root.rowHeight } property int selectedIndex: -1 model: root.model delegate: Rectangle { id: recItemContainer width: parent.width height: bVisible ? root.rowHeight : 0 clip: true property var itemModel: model property bool bVisible: CommonScript.jsBinding(recItemContainer, "bVisible", model ? model.modelData : undefined, "Visible", true) property bool bEnable: CommonScript.jsBinding(recItemContainer, "bEnable", model ? model.modelData : undefined, "Enable", true) property bool isHovered: false Rectangle { id: recHilight color: "#663399FF" anchors.fill: parent anchors.margins: 0 radius: 2 visible: index === listItems.selectedIndex } Rectangle { id: recDisabled color: "#666666" anchors.fill: parent anchors.margins: 0 radius: 2 visible: false //!recItemContainer.bEnable } Rectangle { id: recItemHover color: "#333399FF" anchors.fill: parent anchors.margins: 1 radius: 2 visible: itemMouseArea.containsMouse } Loader { id: listItemLoader sourceComponent: listItem //anchors.fill: parent property var model: recItemContainer.itemModel onLoaded: { adjustPopupWidth(); } function adjustPopupWidth() { var pWidth = CommonScript.max(listItemLoader.item.width, root.dropDownMinWidth) if (pWidth > privateProperties.popupWidth) privateProperties.popupWidthAutoAdjusted = true pWidth = CommonScript.max(pWidth, privateProperties.popupWidth) pWidth = CommonScript.min(pWidth, root.dropDownMaxWidth) root.rowHeight = CommonScript.max(listItemLoader.item.height, root.rowHeight) privateProperties.popupWidth = pWidth if (listItemLoader.width == 0) listItemLoader.width = pWidth } } MouseArea { id: itemMouseArea anchors.fill: parent enabled: recItemContainer.bEnable hoverEnabled: true onClicked: { if (recItemContainer.bEnable) { if (listItems.selectedIndex != index) { listItems.selectedIndex = index listItems.updateSelection() activated(index) } root.popupVisible = false } return true } } } onCurrentIndexChanged: { updateSelection() } function updateSelection () { displayText = "" root.currentIndex = listItems.selectedIndex root.selectedValue = listItems.model[listItems.selectedIndex].binding(root.valueMember) root.selectedItem = listItems.model[listItems.selectedIndex] } } } } property Component listItem: Rectangle { width: recImage.width + lblItemText.contentWidth + 2 * lblItemText.anchors.leftMargin height: MDStyle.textBoxHeight Rectangle { id: recImage width: parent.height height: parent.height anchors.top: parent.top anchors.left: parent.left color: "transparent" visible: root.showIcon Image { id: imgItemIcon width: sourceSize.width height: sourceSize.height anchors.centerIn: parent source: CommonScript.jsBinding(imgItemIcon, "source", model ? model.modelData : undefined, imageSourceMember, "") } } Label { id: lblItemText anchors.left: root.showIcon ? recImage.right : parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: font.pixelSize / 2 font.family: MDStyle.fontFamily font.pixelSize: MDStyle.textFontSize property bool bEnable: CommonScript.jsBinding(lblItemText, "bEnable", model ? model.modelData : undefined, "Enable", true) color: bEnable ? MDStyle.fontColor : MDStyle.fontColorDisable clip: true text: CommonScript.jsBinding(lblItemText, "text", model ? model.modelData : undefined, displayMember, "") } } onCurrentIndexChanged: { if (listItems.selectedIndex != currentIndex) listItems.selectedIndex = currentIndex } onSelectedValueChanged: { updateCurrentIndex() } onModelChanged: { updateCurrentIndex() } function updateCurrentIndex() { if (!selectedValue) { displayText = CommonScript.VariesText } else if (selectedValue === undefined) { console.log("Selected Value is undefined") } else { console.log("Selected Value: " + selectedValue) } displayText = "" if (root.currentIndex >= 0) { if (model[root.currentIndex].binding(valueMember) === selectedValue) return; } for (var i = 0; i < model.length; i++) { if (model[i].binding(valueMember) === selectedValue) { root.currentIndex = i; return; } } } }
  • 0 Votes
    9 Posts
    8k Views
    Aaron HouA

    Certainly, but I don't know how to insert code. They are just like this:

    QDateEdit{ border-radius: 5px; padding: 1px 10px 1px 5px; border: 1px solid #5CACEE; min-height: 30px; } QDateEdit::drop-down { subcontrol-origin: padding; subcontrol-position: top right; **width: 35px; ** border-left-width: 1px; border-left-style: solid; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-left-color: #5CACEE; } QDateEdit::down-arrow { border-image: url(:/Resources/array_down.png); height:30px; width:30px; }

    [edit: added missing coding tags ``` SGaist]