Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to use a normal python module for ttk style definitions #211

Closed
alejandroautalan opened this issue Jun 3, 2023 · 1 comment
Closed
Labels
enhancement New feature or request
Milestone

Comments

@alejandroautalan
Copy link
Owner

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like

Hello Mark,

Wondering if there is a better way of using the style definitions file.
My application is made of up of perhaps a dozen high level widgets generated by pygubu designer. And I use styles everywhere This means that the style code gets generated and included in each widget. This opens the door for these copies to get out of synch where I add/change styles for one widget and forget to regenerate all the other widgets with the changed style file.

I see your problem here. I think that the best solution will be to allow pygubu designer to fully import the styles file as module, and not to execute its content as it is doing now.

Any suggestions here?

I think in some modifications to the designer.

One restriction is that the styles should be created after the root window is instantiated and before any child widget is created. (alejandroautalan/pygubu#282)

Continuing with this idea, the module will need to define the styles inside a method and not at module level. For example, a method named "setup_ttk_styles".

Remove definition file from global configuration and move them to project level properties:

  • ttk style definition file: a python module file. The module file name will be saved in ui file.
  • ttk style setup method: a method of the definition file. Saved in the ui file.

The following example shows how it would look in the future.

Definition file example custom_styles_module.py:

import tkinter as tk
import tkinter.ttk as ttk


def setup_ttk_styles(master=None):

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

Code generated in Application Mode:

#!/usr/bin/python3
import pathlib
import tkinter.ttk as ttk
import pygubu

import custom_styles_module

PROJECT_PATH = pathlib.Path(__file__).parent
PROJECT_UI = PROJECT_PATH / "helloapp.ui"


class HelloappApp:
    def __init__(self, master=None):
    
        self.builder = builder = pygubu.Builder(
            on_first_object=custom_styles_module.setup_ttk_styles)
            
        builder.add_resource_path(PROJECT_PATH)
        builder.add_from_file(PROJECT_UI)
        # Main widget
        self.mainwindow = builder.get_object("toplevel1", master)
        builder.connect_callbacks(self)

    def run(self):
        self.mainwindow.mainloop()


if __name__ == "__main__":
    app = HelloappApp()
    app.run()

Code generated in Script Mode:

#!/usr/bin/python3
import tkinter as tk
import tkinter.ttk as ttk

import custom_styles_module


class HelloappApp:
    def __init__(self, master=None):
        # build ui
        toplevel1 = tk.Tk() if master is None else tk.Toplevel(master)
        toplevel1.configure(height=200, width=200)
        toplevel1.geometry("320x100")
        
        # First object created
        custom_styles_module.setup_ttk_styles(toplevel1)

        frame1 = ttk.Frame(toplevel1)
        frame1.configure(height=200, padding=5, width=200)
        frame2 = ttk.Frame(frame1)
        frame2.configure(height=200, width=200)
        label1 = ttk.Label(frame2)
        label1.configure(text='Hello world!')
        label1.pack(side="top")
        frame2.pack(expand="true", side="top")
        button1 = ttk.Button(frame1)
        button1.configure(text='quit')
        button1.pack(anchor="e", side="top")
        frame1.pack(expand="true", fill="both", side="top")

        # Main widget
        self.mainwindow = toplevel1

    def run(self):
        self.mainwindow.mainloop()


if __name__ == "__main__":
    app = HelloappApp()
    app.run()

Let me know what do you think of this approach.

Regards
Alejandro A.

Originally posted by @alejandroautalan in #204 (comment)

@alejandroautalan
Copy link
Owner Author

Fixed in pygubu-designer v0.37

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant