Search code examples
labelsizewidthgtk3pygobject

How do I resize a Label's width?


I've been trying to resize a label's width for a while, but it seems IMPOSSIBLE, or at least incomprehensible for me...

I'll explain my situation with images for the sake of clarity.

enter image description here

This is how the Window looks with a "Normal" Label...

enter image description here

This is how the Window looks with a ridiculously large text...

enter image description here

Now, THIS IS how I want it to look when text is ridiculously large

See?

Here's the example code:

# -*- coding: utf-8 -*-

import gi
import signal
import hashlib
import random
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Pango

class Test(Gtk.Window):
    def __init__(self):
        def center(a):
            a.props.valign = Gtk.Align.CENTER
            a.props.halign = Gtk.Align.CENTER
        Gtk.Window.__init__(self, title="Test")
        self.set_position(Gtk.WindowPosition.CENTER)
        self.set_border_width(10)
        self.set_resizable(False)
        self.connect("delete-event", Gtk.main_quit)

        Box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
        Button = Gtk.Button("Change Label")
        Label = Gtk.Label()

        Test = "I'm a Label, Yay!"

        center(Box)
        center(Label)
        center(Button)

        Label.set_markup('<span><big>%s</big></span>' % Test)
        Label.set_ellipsize(Pango.EllipsizeMode.END)
        Label.set_justify(Gtk.Justification.LEFT)

        self.add(Box)

        Box.add(Label)
        Box.add(Button)

        #UNKNOWN/FORBIDDEN/DEPRECIATED/INCOMPREHENSIBLE MAGIC!
            #Uncomment only one or both, and watch it's magic!

        #self.set_resizable(True)
        #Box.set_resize_mode(Gtk.ResizeMode.QUEUE)

        def change_label(self):
            Label.set_markup('<span><big>%s</big></span>' % str(hashlib.sha384(str(random.random())).hexdigest()))

        Button.connect("clicked", change_label)

if __name__ == '__main__':
    MainWindow = Test()
    MainWindow.show_all()
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    Gtk.main()

Please note that the Window IS NOT resizable.

If you uncomment one or both of the "Magic" section, you'll see how the Window changes it's behaviour!

BUT

There are two disadvantages while using each one of this approaches:

  • If you uncomment #self.set_resizable(True) WINDOW WILL BECOME RESIZABLE AGAIN, which I don't want it to happen

  • #Box.set_resize_mode(Gtk.ResizeMode.QUEUE) appears to be the "Perfect" solution, but while it does what I want, it seems it has been "Depreciated" in recent versions of Gtk.

Moreover, in some other Window Managers & Themes, It causes some disruptions on Window's dimentions when you change the Label's String a lot of times.

Do you have any suggestions on this?

I'm totally fed up with this. I've been trying for weeks, with no result :c

Maybe there's a way to emulate the behaviour when Window is resizable, while NOT showing Resize Grips & Maximize Button?

Or what's the newer method to do set_resize_mode(Gtk.ResizeMode.QUEUE) ?

PD: Label.set_max_width_chars() isn't what I'm searching for


Solution

  • After hours of research and experimenting, I found another great way to accomplish this task. In my opinion, this is the best way to do it, unless it may be a little limited, but it allows you to do more that the first method and with less code.

    Here's what I've done:

    • From 1° method, I removed the "hackish" code
    • Then, I added a "Mini-Box" object, which is a Gtk.ButtonBox (A special kind of box...) and set it as "Homogeneous"
    • Afterwards, I removed the "Button" object from "Box" and added both "Label" & "Button" objects to the "Mini-Box"
    • Not to mention that I had to add "Mini-Box" to "Box" too...

    Done!

    Here's the example code:

    #!/usr/bin/python2
    
    # -*- coding: utf-8 -*-
    
    import gi
    import signal
    import hashlib
    import random
    import time
    gi.require_version("Gtk", "3.0")
    from gi.repository import Gtk, Pango
    
    class TestWindow(Gtk.Window):
    
        def __init__(self):
    
            Gtk.Window.__init__(self, title="Test")
            self.set_position(Gtk.WindowPosition.CENTER)
            self.set_border_width(10)
            self.set_resizable(False)
            self.connect("delete-event", Gtk.main_quit)
    
            ##Declare Objects
    
            #Boxes
            Box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
            Mini_Box = Gtk.ButtonBox(orientation=Gtk.Orientation.HORIZONTAL, spacing=10, homogeneous=True)
    
            #Buttons
            Button = Gtk.Button.new_with_mnemonic("_Randomize Label")
    
            #Labels
            Label = Gtk.Label()
    
            #Variables & Misc
            Test = "I'm a Label, Yay!" #Label's width should NOT be larger than the Button's size to be displayed entirely, though...
    
            ##Change Objects Properties
    
            #Alignments
            self.center(Box)
    
            #Labels
            Label.set_markup('<span><big>%s</big></span>' % Test)
            Label.set_ellipsize(Pango.EllipsizeMode.END)
            Label.set_justify(Gtk.Justification.LEFT)
    
            ##Packaging
    
            #Boxes
            self.add(Box)
    
            Box.add(Mini_Box)
            Mini_Box.add(Label)
            Mini_Box.add(Button)
    
            def change_label(self):
                Label.set_markup('<span><big>%s</big></span>' % str(hashlib.sha384(str(random.random())).hexdigest()).rstrip())
    
            Button.connect("clicked", change_label)
    
        def center(self, object):
            object.props.valign = Gtk.Align.CENTER
            object.props.halign = Gtk.Align.CENTER
    
    if __name__ == '__main__':
        MainWindow = TestWindow()
        MainWindow.show_all()
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        Gtk.main()
    

    Won't post new screenshots, because the result is the same as above...