remi icon indicating copy to clipboard operation
remi copied to clipboard

[Enhancement] "Frame" widget

Open MikeTheWatchGuy opened this issue 5 years ago • 9 comments

Most of the GUI frameworks have a "Labelled frame" widget. These are container type widgets that group widgets like other containers. It draws a border around the contents and places a label in the upper left corner usually.

Here is what one looks like in tkinter: image

I didn't see anything in the PDF that seemed like the right thing.

Or do I construct one by setting a border on a VBox or HBox?

MikeTheWatchGuy avatar May 09 '19 14:05 MikeTheWatchGuy

@MikeTheWatchGuy I will provide you a solution soon

dddomodossola avatar May 09 '19 18:05 dddomodossola

@MikeTheWatchGuy here is a possible Frame class implementation:

class CLASSframe( gui.Widget ):
    def __init__(self, title, *args, **kwargs):
        super( CLASSframe, self ).__init__(*args, **kwargs)
        self.style.update({"overflow":"visible","border-width":"1px","border-style":"solid","border-color":"#7d7d7d"})
        self.frame_label = Label('frame label')
        self.frame_label.style.update({"position":"relative","overflow":"auto","background-color":"#ffffff","border-width":"1px","border-style":"solid","top":"-7px","width":"95px","height":"24px","left":"10px"})
        self.append(self.frame_label,'frame_label')
        self.set_title(title)

    def set_title(self, title):
        self.frame_label.set_text(title)

dddomodossola avatar May 21 '19 15:05 dddomodossola

@dddomodossola why not the HTML fieldset?

MaxMorais avatar Aug 07 '19 01:08 MaxMorais

Thank you @MaxMorais , this is a really good idea. I will implement this using fieldset!

dddomodossola avatar Aug 07 '19 06:08 dddomodossola

@dddomodossola I thought I would leave my 2 cents here.

I personally implemented this in my wheelers-wort-works-online:

class remi_form(gui.Widget):
	@gui.decorate_constructor_parameter_types([])
	def __init__(self, *args, **kwargs):
		super(remi_form, self).__init__(*args, **kwargs)
		self.type = 'form'

class remi_fieldset(gui.Widget):
	@gui.decorate_constructor_parameter_types([])
	def __init__(self, *args, **kwargs):
		super(remi_fieldset, self).__init__(*args, **kwargs)
		self.type = 'fieldset'

class remi_legend(gui.Widget, gui._MixinTextualWidget):
	@gui.decorate_constructor_parameter_types([str])
	def __init__(self, text='', *args, **kwargs):
		super(remi_legend, self).__init__(*args, **kwargs)
		self.type = 'legend'
		self.set_text(text)

class remi_labelframe(gui.Widget):
	def __init__(self, legend_text='', *args, **kwargs):
		super(remi_labelframe, self).__init__(*args, **kwargs)
		
		self.form = remi_form(width='100%', height='96%')
		self.append(self.form, 'form')
		self.form.style['position'] = 'relative'

		self.fieldset = remi_fieldset(width='100%', height='100%')
		self.form.append(self.fieldset, 'fieldset')
		self.fieldset.style['position'] = 'relative'

		self.legend = remi_legend(text=legend_text)
		self.fieldset.append(self.legend, 'legend') 

jimbob88 avatar May 03 '20 16:05 jimbob88

Thank you a lot @jimbob88 !

dddomodossola avatar May 03 '20 16:05 dddomodossola

I [still] haven't implemented this yet, but think it would be good to do because I made a Sudoku game board that works on the other 3 ports very nicely

sukoku-wx sukoku-qt sukoku-tk

It's one of those "show off" kinds of programs because it's only 1 line of code. To be honest, I personally write them as they feel like little logic puzzles rather than an attempt to show off. They always feel to me like "how can I combine these atoms to make interesting molecules". That's how PySimpleGUI programs feel to me, especially the 1-line ones.

import PySimpleGUI as sg, random

sg.Window('Sudoku',[[sg.Frame('',[[sg.I(random.randint(1,9), justification='r', size=(3,1),key=(frow*3+row,fcol*3+col)) for col in range(3)] for row in range(3)]) for fcol in range(3)] for frow in range(3)]+ [[sg.B('Exit')]]).read()

With the Remi port however, I am temporarily using the Column element as the Frame element. Which means where will be no line drawn around the boxes.

It appears that I'm also not doing the right justification of the inputs either.

image

Right now they way I'm making Column elements it to create a new VBox and recursively call my "packer" code which will put the column's layout inside the VBox just like it were a window.

To show just how primitive and actually easy Remi makes it to do this stuff, here's the code to make a Frame (copied from Column) and add it to a window (or another container like a Column, Frame, etc):

            elif element_type == ELEM_TYPE_FRAME:
                element = element   # type: Frame
                element.Widget = column_widget = remi.gui.VBox()
                if element.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
                    column_widget.style['background-color'] = element.BackgroundColor
                PackFormIntoFrame(element, column_widget, toplevel_form)
                tk_row_frame.append(element.Widget)

The function this code is contained within is PackFormIntoFrame which is where the recursive bit happens.

ANYWAY....

What approach do you suggest I use from the ones listed here?

Do replace VBox with something else?

I'm sorry that while I use Remi throughout my code, I'm not a Remi expert. The reality of the situation is that I have / am writing a single Remi program. (I still feel guilty being able to leverage the power of Remi like this).

PySimpleGUI avatar Jun 03 '20 16:06 PySimpleGUI

image

OMG Davide!!! I got it to work by modifying your little class.....

class CLASSframe( remi.gui.VBox ):
    def __init__(self, title, *args, **kwargs):
        super( CLASSframe, self ).__init__(*args, **kwargs)
        self.style.update({"overflow":"visible","border-width":"1px","border-style":"solid","border-color":"#7d7d7d"})
        self.frame_label = remi.gui.Label('frame label')
        self.frame_label.style.update({"position":"relative","overflow":"auto","background-color":"#ffffff","border-width":"1px","border-style":"solid","top":"-7px","width":"0px","height":"0px","left":"10px"})
        self.append(self.frame_label,'frame_label')
        self.set_title(title)

    def set_title(self, title):
        self.frame_label.set_text(title)

Using the theme "Default" it's easier to see the lines:

image

That has got me thinking that Frame needs to be changed to include being able to set the COLOR for the lines!

I also need to change the code that the text is displayed. The code supplied was placing a large white box at top of the frames for the Sudoku board. The goal for that program was to make a frame with no label, which I managed to do by hacking your supplied class by setting the label size to 0px by 0px.

I have to look at how the other ports look to determine how best to deal with the frame with Remi. It's a relief to know there's a way to do this!!! WOW, what a huge leap forward for the Remi port today. Thank you, as usual, for helping!

PySimpleGUI avatar Jun 03 '20 16:06 PySimpleGUI

Hello @PySimpleGUI ,

I'm really happy you got it working! And compliments about that cool one line example, that's incredible!

dddomodossola avatar Jun 04 '20 07:06 dddomodossola