如何调整标签的宽度?
How do I resize a Label's width?
一段时间以来,我一直在尝试调整标签的宽度,但这似乎是不可能的,或者至少对我来说是不可理解的...
为了清楚起见,我将用图片解释我的情况。
这是 Window 带有 "Normal" 标签的样子...
这就是 Window 带有大得离谱的文字的样子...
现在,这就是我希望文本大得离谱时的样子
看到了吗?
示例代码如下:
# -*- 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()
请注意 Window 不可调整大小。
如果您取消注释一个或两个 "Magic" 部分,您将看到 Window 如何改变它的行为!
但是
使用每一种方法都有两个缺点:
如果您取消注释 #self.set_resizable(True)
WINDOW 将再次调整大小,我不希望它发生
#Box.set_resize_mode(Gtk.ResizeMode.QUEUE)
似乎是 "Perfect" 解决方案,但虽然它符合我的要求,但在最新版本的 Gtk 中似乎是 "Depreciated"。
此外,在其他一些 Window 管理器和主题中,当您多次更改标签的字符串时,它会对 Window 的维度造成一些干扰。
你对此有什么建议吗?
我完全受够了这个。我已经尝试了几个星期,但没有结果 :c
也许有一种方法可以模拟 Window 可调整大小但不显示调整大小手柄和最大化按钮时的行为?
或者更新的方法是什么set_resize_mode(Gtk.ResizeMode.QUEUE)
?
PD:Label.set_max_width_chars()
不是我要搜索的内容
您可能想要了解 Gtk 3.12 中的帧时钟。这里有一个很好的article。
用于排队调整大小的新方法是 Gtk.Widget.queue_resize()
If some state changes that causes the size of your widget to change you call gtk_widget_queue_resize() which will request a layout phase and mark your widget as needing relayout.
我相信下面修改后的示例代码可以满足您的要求。诀窍在于用子框来包围 Gtk.Label
和 Gtk.Button
。然后将 max_width_chars
设置为 1
,将 ellipsize
设置为 END
,将 hexpand
设置为 True
,将 halign
设置为 FILL
在标签上。
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):
Gtk.Window.__init__(self, title="Test")
self.set_size_request(250,-1)
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)
Sub_box_left = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
Sub_box_right = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
Button = Gtk.Button("Change Label")
Label = Gtk.Label()
Test = "I'm a Label, Yay!"
Label.set_markup('<span><big>%s</big></span>' % Test)
Label.set_max_width_chars(1)
Label.set_ellipsize(Pango.EllipsizeMode.END)
Label.set_hexpand(True)
Label.props.halign = Gtk.Align.FILL
Label.set_justify(Gtk.Justification.LEFT)
self.add(Box)
Sub_box_left.add(Label)
Sub_box_right.add(Button)
Box.add(Sub_box_left)
Box.add(Sub_box_right)
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()
好吧,经过一番思考,我找到了一种“hackish”的方法来实现我想要的。
我会尝试用文字来解释它,然后我会 post “最终”代码,但我相信它可以被优化,或者至少我是这样的希望:)
我所做的是获取两个代码(Jacques Gaudin 的原始版本和修改版本),分析它们并创建一个不太复杂的版本。
然后我意识到 Jacques Gaudin 的修改使得 Window set_size_request
依赖于开发人员,因为它需要宽度和高度。
作为“解决方法”,我决定执行以下操作:
- 清理代码
- 让Window不受限制地“出现”,这样它就可以计算出正确显示所需的确切宽度和高度,并立即隐藏window以避免用户按下“随机化按钮”太早了。
- 一旦 Window 隐藏了自己,请求它的确切值(宽度和高度)
- 收集这些值后,Window 仍然隐藏,重新声明
MainWindow
对象,但这次将其参数从 (None, None)
更改为先前收集的值: (Width, Height)
- 接下来,Window 需要重新计算一些内部值,因为更改了它的参数
- 最后,Window 完成重新计算值后,它会再次显示自己,但这次显示所需的宽度和高度,即使由于某种原因标签变大,Window 将保持相同的大小。
我知道这不是“最佳”答案,但至少它有效。
很遗憾,还有几个问题:
- 我们怎样才能使标签“居中”?
- 如果在慢速机器上使用此方法,是否有可能 window 隐藏时会很慢,如果用户提前按下“随机化”按钮会导致某种 bug/glitch ?
- 动态文本翻译怎么样?甚至不需要“重新启动”Window 就可以实现它们吗? (嗯,这不是什么大问题,但还是好奇想一想...)
- 有没有更好的方法来实现这个目标?(最重要的问题:c)
代码如下:
#!/usr/bin/python2
# -*- coding: utf-8 -*-
import gi
import signal
import hashlib
import random
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Pango
class TestWindow(Gtk.Window):
def __init__(self, width, height):
if width is None:
width = -1
if height is None:
height = -1
Gtk.Window.__init__(self, title="Test")
self.set_position(Gtk.WindowPosition.CENTER)
self.set_border_width(10)
self.set_resizable(False)
self.set_size_request(width, height)
self.connect("delete-event", Gtk.main_quit)
##Declare Objects
#Boxes
Box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
#Buttons
Button = Gtk.Button.new_with_mnemonic("Randomize Label")
#Labels
Label = Gtk.Label()
#Variables & Misc
Test = "I'm a Label, Yay!" #You can change me for a bigger label if you want
##Change Objects Properties
#Alignments (Could break things...)
#self.center(Box)
#self.center(Label)
#self.center(Button)
#Labels
Label.set_markup('<span><big>%s</big></span>' % Test)
Label.set_ellipsize(Pango.EllipsizeMode.END)
if width is not -1:
Label.set_max_width_chars(1)
Label.set_justify(Gtk.Justification.FILL)
##Packaging
#Boxes
self.add(Box)
Box.pack_start(Label, True, True, 0)
Box.add(Button)
def change_label(self):
Label.set_markup('<span><big>%s</big></span>' % str(hashlib.sha384(str(random.random())).hexdigest()))
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(None, None)
MainWindow.show_all()
MainWindow.hide()
Width, Height = MainWindow.get_size()
MainWindow = TestWindow(Width, Height)
MainWindow.show_all()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
以下是部分截图:
这是按下按钮的“之前”...
这是“按下按钮后”...
经过数小时的研究和试验,我找到了完成此任务的另一种好方法。在我看来,这是最好的方法,除非它可能有一点限制,但它允许你用更少的代码做比第一种方法更多的事情。
这是我所做的:
- 从 1° 方法中,我删除了 "hackish" 代码
- 然后,我添加了一个"Mini-Box"对象,它是一个Gtk.ButtonBox(一种特殊的盒子...)并将其设置为"Homogeneous"
- 之后,我从 "Box" 中删除了 "Button" 对象,并将 "Label" 和 "Button" 对象添加到 "Mini-Box"
- 更不用说我还必须将 "Mini-Box" 添加到 "Box"...
完成!
示例代码如下:
#!/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()
不会post新截图,因为结果和上面一样...
一段时间以来,我一直在尝试调整标签的宽度,但这似乎是不可能的,或者至少对我来说是不可理解的...
为了清楚起见,我将用图片解释我的情况。
这是 Window 带有 "Normal" 标签的样子...
这就是 Window 带有大得离谱的文字的样子...
现在,这就是我希望文本大得离谱时的样子
看到了吗?
示例代码如下:
# -*- 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()
请注意 Window 不可调整大小。
如果您取消注释一个或两个 "Magic" 部分,您将看到 Window 如何改变它的行为!
但是
使用每一种方法都有两个缺点:
如果您取消注释
#self.set_resizable(True)
WINDOW 将再次调整大小,我不希望它发生#Box.set_resize_mode(Gtk.ResizeMode.QUEUE)
似乎是 "Perfect" 解决方案,但虽然它符合我的要求,但在最新版本的 Gtk 中似乎是 "Depreciated"。
此外,在其他一些 Window 管理器和主题中,当您多次更改标签的字符串时,它会对 Window 的维度造成一些干扰。
你对此有什么建议吗?
我完全受够了这个。我已经尝试了几个星期,但没有结果 :c
也许有一种方法可以模拟 Window 可调整大小但不显示调整大小手柄和最大化按钮时的行为?
或者更新的方法是什么set_resize_mode(Gtk.ResizeMode.QUEUE)
?
PD:Label.set_max_width_chars()
不是我要搜索的内容
您可能想要了解 Gtk 3.12 中的帧时钟。这里有一个很好的article。 用于排队调整大小的新方法是 Gtk.Widget.queue_resize()
If some state changes that causes the size of your widget to change you call gtk_widget_queue_resize() which will request a layout phase and mark your widget as needing relayout.
我相信下面修改后的示例代码可以满足您的要求。诀窍在于用子框来包围 Gtk.Label
和 Gtk.Button
。然后将 max_width_chars
设置为 1
,将 ellipsize
设置为 END
,将 hexpand
设置为 True
,将 halign
设置为 FILL
在标签上。
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):
Gtk.Window.__init__(self, title="Test")
self.set_size_request(250,-1)
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)
Sub_box_left = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
Sub_box_right = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
Button = Gtk.Button("Change Label")
Label = Gtk.Label()
Test = "I'm a Label, Yay!"
Label.set_markup('<span><big>%s</big></span>' % Test)
Label.set_max_width_chars(1)
Label.set_ellipsize(Pango.EllipsizeMode.END)
Label.set_hexpand(True)
Label.props.halign = Gtk.Align.FILL
Label.set_justify(Gtk.Justification.LEFT)
self.add(Box)
Sub_box_left.add(Label)
Sub_box_right.add(Button)
Box.add(Sub_box_left)
Box.add(Sub_box_right)
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()
好吧,经过一番思考,我找到了一种“hackish”的方法来实现我想要的。
我会尝试用文字来解释它,然后我会 post “最终”代码,但我相信它可以被优化,或者至少我是这样的希望:)
我所做的是获取两个代码(Jacques Gaudin 的原始版本和修改版本),分析它们并创建一个不太复杂的版本。
然后我意识到 Jacques Gaudin 的修改使得 Window set_size_request
依赖于开发人员,因为它需要宽度和高度。
作为“解决方法”,我决定执行以下操作:
- 清理代码
- 让Window不受限制地“出现”,这样它就可以计算出正确显示所需的确切宽度和高度,并立即隐藏window以避免用户按下“随机化按钮”太早了。
- 一旦 Window 隐藏了自己,请求它的确切值(宽度和高度)
- 收集这些值后,Window 仍然隐藏,重新声明
MainWindow
对象,但这次将其参数从(None, None)
更改为先前收集的值:(Width, Height)
- 接下来,Window 需要重新计算一些内部值,因为更改了它的参数
- 最后,Window 完成重新计算值后,它会再次显示自己,但这次显示所需的宽度和高度,即使由于某种原因标签变大,Window 将保持相同的大小。
我知道这不是“最佳”答案,但至少它有效。
很遗憾,还有几个问题:
- 我们怎样才能使标签“居中”?
- 如果在慢速机器上使用此方法,是否有可能 window 隐藏时会很慢,如果用户提前按下“随机化”按钮会导致某种 bug/glitch ?
- 动态文本翻译怎么样?甚至不需要“重新启动”Window 就可以实现它们吗? (嗯,这不是什么大问题,但还是好奇想一想...)
- 有没有更好的方法来实现这个目标?(最重要的问题:c)
代码如下:
#!/usr/bin/python2
# -*- coding: utf-8 -*-
import gi
import signal
import hashlib
import random
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Pango
class TestWindow(Gtk.Window):
def __init__(self, width, height):
if width is None:
width = -1
if height is None:
height = -1
Gtk.Window.__init__(self, title="Test")
self.set_position(Gtk.WindowPosition.CENTER)
self.set_border_width(10)
self.set_resizable(False)
self.set_size_request(width, height)
self.connect("delete-event", Gtk.main_quit)
##Declare Objects
#Boxes
Box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
#Buttons
Button = Gtk.Button.new_with_mnemonic("Randomize Label")
#Labels
Label = Gtk.Label()
#Variables & Misc
Test = "I'm a Label, Yay!" #You can change me for a bigger label if you want
##Change Objects Properties
#Alignments (Could break things...)
#self.center(Box)
#self.center(Label)
#self.center(Button)
#Labels
Label.set_markup('<span><big>%s</big></span>' % Test)
Label.set_ellipsize(Pango.EllipsizeMode.END)
if width is not -1:
Label.set_max_width_chars(1)
Label.set_justify(Gtk.Justification.FILL)
##Packaging
#Boxes
self.add(Box)
Box.pack_start(Label, True, True, 0)
Box.add(Button)
def change_label(self):
Label.set_markup('<span><big>%s</big></span>' % str(hashlib.sha384(str(random.random())).hexdigest()))
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(None, None)
MainWindow.show_all()
MainWindow.hide()
Width, Height = MainWindow.get_size()
MainWindow = TestWindow(Width, Height)
MainWindow.show_all()
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
以下是部分截图:
这是按下按钮的“之前”...
这是“按下按钮后”...
经过数小时的研究和试验,我找到了完成此任务的另一种好方法。在我看来,这是最好的方法,除非它可能有一点限制,但它允许你用更少的代码做比第一种方法更多的事情。
这是我所做的:
- 从 1° 方法中,我删除了 "hackish" 代码
- 然后,我添加了一个"Mini-Box"对象,它是一个Gtk.ButtonBox(一种特殊的盒子...)并将其设置为"Homogeneous"
- 之后,我从 "Box" 中删除了 "Button" 对象,并将 "Label" 和 "Button" 对象添加到 "Mini-Box"
- 更不用说我还必须将 "Mini-Box" 添加到 "Box"...
完成!
示例代码如下:
#!/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()
不会post新截图,因为结果和上面一样...