将固定大小的GtkDrawingArea小部件居中放置在父小部件内

2 投票
2 回答
1594 浏览
提问于 2025-04-16 16:12

我正在使用 Glade 设计一个布局,其中有一个固定大小的 GtkDrawingArea。现在相关的层级结构是:

GtkWindow > GtkVBox > GtkHPaned > GtkViewport > GtkAlignment > GtkFixed > GtkDrawingArea

目前,GtkFixed 小部件是在 GtkViewport 的左上角绘制的。

不过,我希望 GtkFixed(以及它唯一的子部件 GtkDrawingArea)能够在 GtkViewport 中居中显示(当然,当小部件被压缩到无法容纳内容并出现滚动条时除外)。

有什么好的方法可以实现这个目标呢? (我在用 pygtk 来处理实际的应用逻辑,但这应该是一个通用的 gtk 问题)

这里有一段代表性的代码示例:

import gtk

class Controller:

    def on_window1_destroy(self, widget, data=None):
        gtk.main_quit()

    def __init__(self):
        self.builder = gtk.Builder()
        self.builder.add_from_file("sample.glade")
        self.window = self.builder.get_object("window1")
        self.builder.connect_signals(self)

    def on_drawingarea1_expose_event(self, widget, event):
        cr = widget.window.cairo_create()
        cr.set_source_rgb(0,0,0)
        cr.paint()
        return True

if __name__ == "__main__":
    client = Controller()
    client.window.show()
    gtk.main()

还有一个包含相同问题的 Glade 文件:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window1">
    <signal name="destroy" handler="on_window1_destroy"/>
    <child>
      <object class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <child>
          <object class="GtkHPaned" id="hpaned1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <child>
              <object class="GtkLabel" id="label1">
                <property name="visible">True</property>
                <property name="label" translatable="yes">label</property>
              </object>
              <packing>
                <property name="resize">False</property>
                <property name="shrink">True</property>
              </packing>
            </child>
            <child>
              <object class="GtkScrolledWindow" id="scrolledwindow1">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="hscrollbar_policy">automatic</property>
                <property name="vscrollbar_policy">automatic</property>
                <child>
                  <object class="GtkAlignment" id="alignment1">
                    <property name="visible">True</property>
                    <child>
                      <object class="GtkFixed" id="fixed1">
                        <property name="width_request">300</property>
                        <property name="height_request">300</property>
                        <property name="visible">True</property>
                        <child>
                          <object class="GtkDrawingArea" id="drawingarea1">
                            <property name="width_request">300</property>
                            <property name="height_request">300</property>
                            <property name="visible">True</property>
                            <signal name="expose_event" handler="on_drawingarea1_expose_event"/>
                          </object>
                        </child>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
              <packing>
                <property name="resize">True</property>
                <property name="shrink">True</property>
              </packing>
            </child>
          </object>
          <packing>
            <property name="position">0</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

最后... 这是问题的示例图片... Screeshot @ imgur

2 个回答

0

固定的元素会占用所有可用的空间,所以你需要在它的父元素上捕捉到大小变化的事件,可以是视口(Viewport)或者固定元素本身。我猜视口可能更有效。然后,你需要获取固定元素的大小,并根据固定元素的大小和子元素的大小来调整子元素的位置。

你可以通过视口来获取子组件,或者通过绘图区域(DrawingArea)来获取父组件。

7

在GTK 2.x中,你可以添加一个GtkAlignment作为你想要居中对齐的内容的父级,并把对齐设置为0.5(关闭填充)。

在3.x版本中,所有的控件都有xalign和yalign这两个属性,可以设置为CENTER来实现居中。

更新一下:从示例的glade文件来看,问题在于填充没有被关闭;我之前懒得查这些属性的名称。在GtkAlignment中,xscale=0.0和yscale=0.0的意思是不要让子控件扩展去填满可用空间。默认的xscale=1.0和yscale=1.0意味着子控件会填满可用空间,这样居中就没有效果了。

在示例的Glade文件中,我还需要做“添加父级 -> 视口”,这样才能在滚动窗口和对齐之间添加一个视口。你应该会在控制台看到关于这个的警告。

撰写回答