alejandroautalan / pygubu-designer

A simple GUI designer for the python tkinter module
GNU General Public License v3.0
836 stars 102 forks source link

User defined styles not appearing in the style property combobox #181

Closed dsurgenavic closed 1 year ago

dsurgenavic commented 1 year ago

When I define my own ttk styles, they do not appear as options in the style property combobox. The styles are still applied to the preview and code generation if I type the style name.

jrezai commented 1 year ago

Hi @dsurgenavic ,

What kind of widget is the style being applied to? Ttk button, Ttk label...? Could you share your style code that's not showing up, from your style definition file?

What version of Pygubu Designer are you using? Which OS?

dsurgenavic commented 1 year ago

The issue is with version 0.33, though I had the issue with version 0.29 before updating. I am using Windows 10.

The issue persists with all ttk widgets, and the style code that is not showing up is just the sample code generated by clicking 'Create New...' under style preferences:

style = Style()

style.configure(
    "MySpecialButton.TButton",
    font=("helvetica", 12, "bold"),
    background="green", foreground="white"
)

In my testing I changed TButton to different widget names. The style still does not show up in the property combobox, but will always be displayed in the preview if I type the style name in.

alejandroautalan commented 1 year ago

Hello @dsurgenavic, thanks for trying pygubu.

Can you post your python version ? I still can't reproduce the error.

Regards.

jrezai commented 1 year ago

The style, MySpecialButton.TButton is specific to ttk buttons.

If MySpecialButton.TButton, for example, gets renamed to MySpecialButton.TLabel, then the style combobox for a ttk Button will no longer show that style in the combobox, because it won't be meant for a button (some styles for a button might be the same as a label, but some style configurations could be unique, so if you share the same style for multiple widgets you may get unexpected results). In the case of a label and button, both have fonts and backgrounds, so they share the same kind of style properties. But a style definition may not always be so simple or may not share the same properties as another widget.

For example, try using that same style for a ttk Scrollbar and you should see some strange results.

So after the style gets renamed to MySpecialButton.TLabel, the style will be populated for a ttk Label in the Style combobox, but no longer for a ttk button.

In other words, if you use: MySpecialButton.TButton, that style will only populate for ttk Buttons MySpecialButton.TLabel will only popululate for ttk Labels etc..

Generally speaking, each derived style should be for one type of widget.

However if a style isn't derived from an existing widget, then I think it would make sense to have it populate for all style comboboxes because it won't be attached to any specific types of widgets. What is your opinion on this @alejandroautalan ? This could potentially be a change request.

dsurgenavic commented 1 year ago

@alejandroautalan I am using Python 3.10

In response to this:

If MySpecialButton.TButton, for example, gets renamed to MySpecialButton.TLabel, then the style combobox for a ttk Button will no longer show that style in the combobox, because it won't be meant for a button

I realize now how it seems in my last comment, I should have ben clearer. I was describing my method of testing whether the error persists for all different widgets. If I change MySpecialButton.TButton to MySpecialButton.TLabel, the style does not appear in the combobox for styling a Label. I did not expect this to populate the style combobox for button. I apologize for the confusion.

Is there a specific location that I should put the style definition file? I have it in my project files with the the rest of the program scripts if that information helps.

dsurgenavic commented 1 year ago

I have found the issue. In my style definition file I was using an import statement:

from tkinter.ttk import Style

style = Style()

style.configure(
    "MySpecialButton.TButton",
    font=("helvetica", 12, "bold"),
    background="green", foreground="white"
)

Removing this import statement and the line style = Style() lets the comboboxes be populated with the defined styles, though now there is an error when attempting to run my program. The solution is that the style definition program should not run.

This seems rather silly to me. Instead of defining my styles once, I need to define them all at least twice to allow Pygubu Designer to work properly.

jrezai commented 1 year ago

Removing this import statement and the line style = Style() lets the comboboxes be populated with the defined styles, though now there is an error when attempting to run my program.

Right, there is no need to instantiate Style() from the style definition file, it's already instantiated in Pygubu Designer.

Instead of defining my styles once, I need to define them all at least twice to allow Pygubu Designer to work properly.

I don't understand. Can you provide an example? All styles should be put into one definition file. When you're finished, you can generate code in Pygubu Designer so that it includes the styles that you defined. In the Code tab (in Pygubu Designer), there is a checkbutton that says 'Use ttk style definitions file'. When that is checked, it'll generate code from your style definition file.

dsurgenavic commented 1 year ago

Instead of defining my styles once, I need to define them all at least twice to allow Pygubu Designer to work properly.

In the code, the styles must be defined in the file read by Pygubu Designer, and they must also be defined to be used by the program.

you can generate code in Pygubu Designer so that it includes the styles that you defined

This is exactly what I mean. However, there may be a case where a user may not want to use Pygubu Designer for a window. In that case, the user still must define the style and will not be able to import from the style definition file.

On the other hand, having Pygubu Designer generate code to include the style feels a little clunky to me because having the same code in multiple places is redundant. There is also the problem that now I must have a script in my program that intentionally has errors, even if the script does not run.

alejandroautalan commented 1 year ago

Hello @dsurgenavic, sorry for the inconvenience.

In order to populate the style combo-box and preview your defined styles you can use a style definition file. This is a file where you define your style using only the provided style object, you can use local variables and other python expressions but you can't use imports.

The style definition file it is not designed to be part of the final application, but as a place where pygubu-designer can read the styles and preview them live.

I will study your problem and search some alternative solutions to improve this functionality.

Regards Alejandro A.

Goldthing commented 1 year ago

Hi @alejandroautalan, I saw this discussion and I too would like have a functional style definition file.

I think I have a relativley simple solution to the problem. Looking through the code if I'm right the file is read in here before being passed along. Simply striping the offending

from tkinter.ttk import Style style = Style()

before passing to self._apply_ttk_styles(contents) should allow everything to coexist nicely without adding too much overhead.

I can try to put a pull request together if you think it would be a good approach.

alejandroautalan commented 1 year ago

Hello, regarding this issue:

The style definition file it is not designed to be part of the final application, but as a place where pygubu-designer can read the styles and preview them live. I will study your problem and search some alternative solutions to improve this functionality.

This will change in the next version, allowing to use a regular python module for defining styles. See #211