How to make a input form as this picture.

Hi sir,
Here was my input form in tcl

as you can see the UI input table ,I can make 2 or more input item as this code.

  set f [frame .top.f2]
  pack $f -fill both -pady 5
  label $f.lab3 -text "for Oval long-side:" -width 25 -anchor w
  label $f.lab4 -text "short-side:" -width 12 -anchor w
  entry $f.ent3 -bg white -textvariable BiasL -width 10
  entry $f.ent4 -bg white -textvariable BiasS -width 10
  pack  $f.lab3 $f.ent3 $f.lab4 $f.ent4 -side left -padx 5 

But , in the Klayout Ruby (DRC) ,
Here was my code , I can just make label in 1 line , input item in next line...
that will make a little issue .... we have many value needs designer to input into our UI table.
so , that will make UI table very long....
What /how can I do for the coding ?

    dialog.windowTitle = "UnitDIE design (for Dialog) 2023-06-20"
    formlayout = RBA::QVBoxLayout::new(dialog)
    dialog.setLayout(formlayout)

    label =  RBA::QLabel.new(dialog)
    formlayout.addWidget(label)
    label.text = "Input PSV type...."
    pm_type =  RBA::QComboBox.new(dialog)
    pm_type.addItem("PI")
    pm_type.addItem("PBO")
    formlayout.addWidget(pm_type)

by the way , may I shown a picture (*.gif or *.jpeg) into UI input table?

Comments

  • edited June 2023

    Better to use Qt Designer for a complicated UI design.
    See the "Designer Dialog Sample" of the Macro editor on how to import a *.ui file designed by Qt Designer.

    I mimicked your desired UI design: "ReUBM.[ui|qrc|rcc]" in the attached ZIP file.

    Regarding images, you can refer to https://www.klayout.de/forum/discussion/636/images-in-qdialog

    Generate a binary resource file *.rcc using Qt's resource compiler.

        $ rcc -binary ReUBM.qrc > ReUBM.rcc
    

    Then register it in the Ruby script.


    In the macro editor...

    The image is nothing but the label of the big button.

  • Hi sir,
    Thanks a lot for your code , but Unlucky , I am not expert for Ruby.
    I just want to base on Klayout Ruby DRC to make a UI for user to let they input some value.
    I will check what your recommend , maybe I need to research more data for that.
    Thanks again.

  • @kazzz I did not know that you can register resources that way! Many thanks for this document!

    Matthias

  • edited July 2023

    Hi jiunnweiyeh

    seems like you are trying to create a DRC UI and requires a lot of repeated components that is tedious to define one-by-one.

    here's an example of wraping a group custom component in to a reusable CustomListItem object, which might able to reduce the work.

    please check the last 10 lines of code, which use predefined custom widget to create the input form

    include RBA
    
    class LayerSelectWidget < RBA::QWidget
        def initialize(labelTitle)
            layerInfo = RBA::LayoutView.current().active_cellview().layout().layer_infos()
            layerList = layerInfo.map{ |inf| "#{inf.layer}/#{inf.datatype}"}
            @layout   = RBA::QHBoxLayout::new()
            @label    = RBA::QLabel::new(labelTitle)
            @dropdown = RBA::QComboBox::new()
            @suffix   = RBA::QLabel::new("")
            @suffix.setFixedWidth(30)
            @dropdown.setFixedWidth(100)
            @dropdown.addItems(layerList)
            @layout.addWidget(@label)
            @layout.addWidget(@dropdown)
            @layout.addWidget(@suffix)
            setLayout(@layout)
        end
    
        def getValue()
            return [@label.text, @dropdown.currentText]
        end
    end
    class OptionSelectWidget < RBA::QWidget
        def initialize(labelTitle, optionList = [], suffix = "")
            @layout   = RBA::QHBoxLayout::new()
            @label    = RBA::QLabel::new(labelTitle)
            @dropdown = RBA::QComboBox::new()
            @suffix   = RBA::QLabel::new(suffix)
            @suffix.setFixedWidth(30)
            @dropdown.setFixedWidth(100)
            @dropdown.addItems(optionList)
            @layout.addWidget(@label)
            @layout.addWidget(@dropdown)
            @layout.addWidget(@suffix)
            setLayout(@layout)
        end
    
        def getValue()
            return [@label.text, @dropdown.currentText]
        end
    end
    class IntNumberWidget < RBA::QWidget
        def initialize(labelTitle, value = 0, suffix = "", minVal = -1000, maxVal = 1000)
            @layout   = RBA::QHBoxLayout::new()
            @label    = RBA::QLabel::new(labelTitle)
            @spinbox  = RBA::QSpinBox::new()
            @suffix   = RBA::QLabel::new(suffix)
            @suffix.setFixedWidth(30)
            @spinbox.setFixedWidth(100)
            @spinbox.setRange(minVal, maxVal)  
            @spinbox.setValue(value)
            @layout.addWidget(@label)
            @layout.addWidget(@spinbox)
            @layout.addWidget(@suffix)
            setLayout(@layout)
        end
    
        def getValue()
            return [@label.text, @spinbox.value]
        end
    end
    
    class DblNumberWidget < RBA::QWidget
        def initialize(labelTitle, value = 0, suffix = "", minVal = -1000, maxVal = 1000)
            @layout   = RBA::QHBoxLayout::new()
            @label    = RBA::QLabel::new(labelTitle)
            @spinbox  = RBA::QDoubleSpinBox::new()
            @suffix   = RBA::QLabel::new(suffix)
            @suffix.setFixedWidth(30)
            @spinbox.setFixedWidth(100)
            @spinbox.setRange(minVal, maxVal)  
            @spinbox.setValue(value)
            @layout.addWidget(@label)
            @layout.addWidget(@spinbox)
            @layout.addWidget(@suffix)
            setLayout(@layout)
        end
    
        def getValue()
            return [@label.text, @spinbox.value]
        end
    end
    
    
    class RuleListWidget < RBA::QListWidget
        def initialize()
            setSelectionMode(RBA::QAbstractItemView::ExtendedSelection)
            setStyleSheet( """
                QListWidget{
                    background: #f9f9f9;
                }
    
                QListWidget::item {
                    border-style: solid;
                    border-width:1px;
                    border-color:#aeaeae; 
                    background-color: #eeeeee;
                }
    
                QListWidget::item:selected {
                    border-style: solid;
                    border-width:1px;
                    border-color:#aeaeae; 
                    background-color: #dfdfdf;
                }""")
        end
    
        def addCustomWidget(customWidget)
            listItemWidget = RBA::QListWidgetItem.new()
            listItemWidget.setSizeHint(customWidget.sizeHint())
            addItem(listItemWidget)
            setItemWidget(listItemWidget, customWidget)
        end
    
        def getListItemValue()
            for index in 0..count-1 do
                listItemWidget = item(index)
                customWidget   = itemWidget(listItemWidget)
                widgetValue    = customWidget.getValue()
                puts "#{index} #{widgetValue[0]} : #{widgetValue[1]}"
            end
        end
    end
    
    class MainWidget < RBA::QWidget
        def initialize()
            @okButton       = RBA::QPushButton.new("OK")
            @cancelButton   = RBA::QPushButton.new("Cancel")
            @ruleListWidget = RuleListWidget.new()
            @buttonLayout   = RBA::QHBoxLayout::new()
            @mainLayout     = RBA::QVBoxLayout::new()
    
            @buttonLayout.addWidget(@okButton)
            @buttonLayout.addWidget(@cancelButton)
            @mainLayout.addWidget(@ruleListWidget)
            @mainLayout.addLayout(@buttonLayout)
            setLayout(@mainLayout)
            resize(400, 400)
            setWindowTitle ("UnitDIE design (for Dialog) 2023-06-20")
            @okButton.clicked do @ruleListWidget.getListItemValue() end
            @cancelButton.clicked do close() end
    
        end
    
        def addCustomWidget(customWidget)
            @ruleListWidget.addCustomWidget(customWidget)
        end
    
    end
    lv = RBA::LayoutView.current()
    if !(lv== nil)
        ly = lv.active_cellview().layout()
    
        widget = MainWidget.new()
    
        #these 10 lines of code defines UI CustomListWidgets
        widget.addCustomWidget(OptionSelectWidget.new("Input PSV Type", ["PI", "PBO"]))
        widget.addCustomWidget(LayerSelectWidget.new("Input Top Metal Layer"))
        widget.addCustomWidget(LayerSelectWidget.new("Input PSV Layer"))
        widget.addCustomWidget(LayerSelectWidget.new("Input RDL Layer"))
        widget.addCustomWidget(LayerSelectWidget.new("Input UBM Layer"))
        widget.addCustomWidget(DblNumberWidget.new("Input Rule_A (PM1 size)",  22, "um"))
        widget.addCustomWidget(DblNumberWidget.new("Input Rule_B (PSV to PM1)", 7, "um"))
        widget.addCustomWidget(DblNumberWidget.new("Input RDL Bump size",       8, "um"))    
        widget.addCustomWidget(DblNumberWidget.new("Input PM2 size",            9, "um"))
        widget.show()
    end 
    
  • edited July 2023

    Hi jiunnweiyeh

    incase you need to embed a image into your widget without any external path dependency, you can try to convert the image in to a base64 string and paste it into your code.

    here's an example of how to embed image into your program:

    include RBA
    require "base64"
    class EmbededImageWidget < RBA::QWidget
        def initialize(base64Image)
            @layout      = RBA::QHBoxLayout::new()
            @pixmap      = RBA::QPixmap.new()
            @label       = RBA::QLabel.new()
            @pixmap.loadFromData(Base64.decode64(base64Image))
            @label.setPixmap(@pixmap)
            @layout.addWidget(@label)
            @layout.setMargin(0)
            setLayout(@layout)
        end
    end
    e = EmbededImageWidget.new("iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAAM1BMVEXR0tT8/PzU1dfo6era2tz09PT29/fi4+Td3d/u7u/5+frr6+z////X2Nnl5uff4OHx8fIVPDPXAAACdUlEQVR4Xu1a2W4DIQxcm5s9//9rqx6KthZkMESoUjOPkcLExmN8ZPkneOMNjia5vP0gu2Qiv5bhXP1WgF/PVzHERFsVlOI4A4e8AeSDxygMbQ0gM0ATaGsEHZ0U1m0KeNvDYTYljJpi92W3uC9Q2ZhdGbZUEsXNI7YkHVKFc5AMV+BSeF+SJrRzHDJCq37YZYw3R1mSItBIKfXYsUKd8aq3Jeij33rlvcRfZiyN+GVMhPq4eZhCXwYipBd/41AlCntj8SCXAA7MgjOMFRzdLBY5C3NgFtekkLB0IDR8nwnEriKSieGte0SA/W2gIbaXxCJTDuwsjBXcShb+BEDuyM+TllkGYJ6msFQzhKNVmlJ/WahsiPnyYtr1plChpn6YeT+PvVqd++Ogs66jS3CoWa66osVPFsyamAtVSfPjMBYf4scbHyUD2Mt7esCpc0usxcRaLYezWvWmppJznOSsKcWVcmME7kJZ0tUSl1AvuvjgPu9RNHQ124VMUQhLHWVbTB4VEicPEfoVHOWawClIYFpJlRvDJALhk4bSXsxSd0QdiUTkpvJfT6JvXd0fI6FuklQKYSxGrOw7Ahaj6ym53F2rOK3IBKmv40+QIEWqV+Ckp++pAY9WI/ZvD1wWPFrgzYSIMXLrUfraR19ILCuUo74kgsUdBi7uYJk6XnETLrjHe4c0sXWY3wQt4bXt3DGlMYUtNo+32FOHBRLhdWOPA75C4wMcP2UUNWOoNmM8OHHQOX9kO3/4PD5Gn7MQmL/aGF/SOLCkGV03BbBumrY4m78CxNGP4Xpf04NaKXKYvGDWg4+MreC/v/THf1+Y8EeM/4E33vgA3zF0CgdXgLYAAAAASUVORK5CYII=")
    e.show()
    


    and here's how you convert a image into base64 string:
    1. goto this site : https://www.base64-image.de/
    2. drag and drop image into window for upload and conversion
    3. after upload completed, click show code
    4. copy every thing that is after data:image/png;base64, and paste to your code

  • Hi Rawr,
    got it , I will try it
    (actually , I can make some simple code , look like that will over my current capbility..)
    any way , Thanks for your help , I will try my best .

  • edited July 2023

    Hi jiunnweiyeh

    I think i made the example abundantly long, the basic idea is to create a customWidget and make it reusable.

    following code is a bare minimum example of creates a OptionSelectWidget class that inherts QWidget
    in initalize function you define the ui components and place them into layout as usual
    which it will be called once the widget is being created
    this init function can take values such as title and list of options for later use.

    rest of the part i ust copy from your exampl and replace them with custom widgets

    include RBA
    class OptionSelectWidget < RBA::QWidget
        def initialize(labelTitle, optionList = [], suffix = "")
            @layout   = RBA::QHBoxLayout::new()
            @label    = RBA::QLabel::new(labelTitle)
            @dropdown = RBA::QComboBox::new()
            @suffix   = RBA::QLabel::new(suffix)
            @suffix.setFixedWidth(30)
            @dropdown.setFixedWidth(100)
            @dropdown.addItems(optionList)
            @layout.addWidget(@label)
            @layout.addWidget(@dropdown)
            @layout.addWidget(@suffix)
            setLayout(@layout)
        end
    
        def getValue()
            return [@label.text, @dropdown.currentText]
        end
    end
    
    dialog = RBA::QWidget::new()
    dialog.windowTitle = "UnitDIE design (for Dialog) 2023-06-20"
    formlayout = RBA::QVBoxLayout::new(dialog)
    dialog.setLayout(formlayout)
    formlayout.addWidget( OptionSelectWidget.new("Input PSV1 Type", ["PI", "PBO"]))
    formlayout.addWidget( OptionSelectWidget.new("Input PSV2 Type", ["PI", "PBO"]))
    formlayout.addWidget( OptionSelectWidget.new("Input PSV3 Type", ["PI", "PBO"]))
    formlayout.addWidget( OptionSelectWidget.new("Input PSV4 Type", ["PI", "PBO"]))
    dialog.show()
    
  • Hi Rawr ,
    Thanks for your help , I will try to make it into my current code.
    Thanks.

Sign In or Register to comment.