Gtkmm - 更改 Window 的最小大小
Gtkmm - change minimum size of Window
我尝试更改 Gtk::Window 的最小大小。应该可以将 window 缩小到比其中最大的容器更小的特定尺寸。
我尝试了几种方法,您可以在下面看到。没有任何效果。最小值始终由图像大小定义。我做错了什么?
main.cpp
#include "MainWindow.h"
#include <gtkmm.h>
int main (int argc, char* argv[])
{
Glib::RefPtr<Gtk::Application> app =
Gtk::Application::create(argc, argv, "org.gtkmm.example");
MainWindow mainWindow;
return app->run(mainWindow);
}
MainWindow.h
#ifndef MAINWINDOW_H_INCLUDED
#define MAINWINDOW_H_INCLUDED
#include <gtkmm.h>
#include <gdkmm.h>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
private:
Gtk::Image m_Image;
};
#endif // MAINWINDOW_H_INCLUDED
MainWindow.cpp
#include "MainWindow.h"
#define APPROACH_05
MainWindow::MainWindow() :
m_Image( "image.png" )
{
this->set_border_width(0);
#ifdef APPROACH_01
this->add(m_Image);
m_Image.set_size_request(5,5);
#endif // APPROACH_01
#ifdef APPROACH_02
this->add(m_Image);
this->set_size_request(5,5);
#endif // APPROACH_02
#ifdef APPROACH_03
this->add(m_Image);
Gtk::Allocation allocation = m_Image.get_allocation();
allocation.set_width(5);
allocation.set_height(5);
m_Image.set_allocation(allocation);
#endif // APPROACH_03
#ifdef APPROACH_04
this->add(m_Image);
Gtk::Allocation allocation = this->get_allocation();
allocation.set_width(5);
allocation.set_height(5);
this->set_allocation(allocation);
#endif // APPROACH_04
#ifdef APPROACH_05
this->add(m_Image);
Gdk::Geometry geom = {
.min_width = 5,
.min_height = 5,
};
Gtk::Window::set_geometry_hints(*this,geom,Gdk::HINT_MIN_SIZE);
#endif // APPROACH_05
this->show_all_children();
}
编译为:
g++ main.cpp MainWindow.cpp `pkg-config gtkmm-3.0 --cflags --libs` -o prog
@ptomato 感谢您的回复。我试过这样:
#ifdef APPROACH_06
this->add(m_ScrolledWindow);
m_ScrolledWindow.set_border_width(0);
m_ScrolledWindow.set_policy(Gtk::POLICY_NEVER,Gtk::POLICY_ALWAYS);
m_ScrolledWindow.add(m_Image);
#endif // APPROACH_06
现在我可以垂直调整 window 的大小,但我看到了垂直滚动条。如果我将策略设置为 POLICY_NEVER
,就像在水平轴上一样,window 宽度被限制为图像宽度。此外,滑块的大小也限制了高度。
如果您希望能够将 window 缩小到比其中的图像更小的尺寸,那么您需要先将图像放在 Gtk::ScrolledWindow
中,然后再将其添加到window。如果不滚动,当您使 window 小于图像时,图像将不知道要渲染自己的哪一部分。
有一种方法可以在 window 及其内容之间添加一个层,该层由自定义容器组成,该容器位于父级 window 的首选大小左右。
这是我的重写 GtkFixed 解决了完全相同的问题:
reckless_fixed.h
#ifndef __RECKLESS_FIXED_H__
#define __RECKLESS_FIXED_H__
#ifndef NO_INCLUDE_WITHIN_HEADERS
#include <gtk/gtk.h>
#endif
#define RECKLESS_FIXED_TYPE (reckless_fixed_get_type ())
#define RECKLESS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RECKLESS_FIXED_TYPE, RecklessFixed))
#define RECKLESS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RECKLESS_FIXED_TYPE, RecklessFixedClass))
#define IS_RECKLESS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RECKLESS_FIXED_TYPE))
#define IS_RECKLESS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RECKLESS_FIXED_TYPE))
#define RECKLESS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RECKLESS_FIXED_TYPE, RecklessFixedClass))
typedef struct _RecklessFixed RecklessFixed;
typedef struct _RecklessFixedClass RecklessFixedClass;
struct _RecklessFixed
{
GtkFixed container;
};
struct _RecklessFixedClass
{
GtkFixedClass container_class;
};
GType reckless_fixed_get_type(void);
GtkWidget* reckless_fixed_new(void);
static void reckless_fixed_get_preferred_width(GtkWidget *widget, int *minimal, int *natural);
static void reckless_fixed_get_preferred_height(GtkWidget *widget, int *minimal, int *natural);
#endif /* __RECKLESS_FIXED_H__ */
reckless_fixed.c
#include <gtk/gtk.h>
#include "reckless_fixed.h"
G_DEFINE_TYPE( RecklessFixed, reckless_fixed, GTK_TYPE_FIXED )
static void reckless_fixed_class_init( RecklessFixedClass* klass ) {
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
widget_class->get_preferred_width = reckless_fixed_get_preferred_width;
widget_class->get_preferred_height = reckless_fixed_get_preferred_height;
}
static void reckless_fixed_init( RecklessFixed* self ) {}
// here is where we are reckless about our content's size
static void reckless_fixed_get_preferred_width(GtkWidget *widget, int *minimal, int *natural) {
*minimal = *natural = 1;
}
//here too
static void reckless_fixed_get_preferred_height(GtkWidget *widget, int *minimal, int *natural) {
*minimal = *natural = 1;
}
GtkWidget* reckless_fixed_new (void) {
return g_object_new (RECKLESS_FIXED_TYPE, NULL);
}
请注意GTK版本-上面的例子适用于GTK-3.0。对于 <=2.0,存在 ::size-request 信号,通过连接和应答实现相同的目标。
此外,我会警告这种方法 - 仅在您完全确定自己在做什么以及为什么需要 content-independent window resize,因为这会破坏内置的 GTK 布局系统。
我尝试更改 Gtk::Window 的最小大小。应该可以将 window 缩小到比其中最大的容器更小的特定尺寸。
我尝试了几种方法,您可以在下面看到。没有任何效果。最小值始终由图像大小定义。我做错了什么?
main.cpp
#include "MainWindow.h"
#include <gtkmm.h>
int main (int argc, char* argv[])
{
Glib::RefPtr<Gtk::Application> app =
Gtk::Application::create(argc, argv, "org.gtkmm.example");
MainWindow mainWindow;
return app->run(mainWindow);
}
MainWindow.h
#ifndef MAINWINDOW_H_INCLUDED
#define MAINWINDOW_H_INCLUDED
#include <gtkmm.h>
#include <gdkmm.h>
class MainWindow : public Gtk::Window
{
public:
MainWindow();
private:
Gtk::Image m_Image;
};
#endif // MAINWINDOW_H_INCLUDED
MainWindow.cpp
#include "MainWindow.h"
#define APPROACH_05
MainWindow::MainWindow() :
m_Image( "image.png" )
{
this->set_border_width(0);
#ifdef APPROACH_01
this->add(m_Image);
m_Image.set_size_request(5,5);
#endif // APPROACH_01
#ifdef APPROACH_02
this->add(m_Image);
this->set_size_request(5,5);
#endif // APPROACH_02
#ifdef APPROACH_03
this->add(m_Image);
Gtk::Allocation allocation = m_Image.get_allocation();
allocation.set_width(5);
allocation.set_height(5);
m_Image.set_allocation(allocation);
#endif // APPROACH_03
#ifdef APPROACH_04
this->add(m_Image);
Gtk::Allocation allocation = this->get_allocation();
allocation.set_width(5);
allocation.set_height(5);
this->set_allocation(allocation);
#endif // APPROACH_04
#ifdef APPROACH_05
this->add(m_Image);
Gdk::Geometry geom = {
.min_width = 5,
.min_height = 5,
};
Gtk::Window::set_geometry_hints(*this,geom,Gdk::HINT_MIN_SIZE);
#endif // APPROACH_05
this->show_all_children();
}
编译为:
g++ main.cpp MainWindow.cpp `pkg-config gtkmm-3.0 --cflags --libs` -o prog
@ptomato 感谢您的回复。我试过这样:
#ifdef APPROACH_06
this->add(m_ScrolledWindow);
m_ScrolledWindow.set_border_width(0);
m_ScrolledWindow.set_policy(Gtk::POLICY_NEVER,Gtk::POLICY_ALWAYS);
m_ScrolledWindow.add(m_Image);
#endif // APPROACH_06
现在我可以垂直调整 window 的大小,但我看到了垂直滚动条。如果我将策略设置为 POLICY_NEVER
,就像在水平轴上一样,window 宽度被限制为图像宽度。此外,滑块的大小也限制了高度。
如果您希望能够将 window 缩小到比其中的图像更小的尺寸,那么您需要先将图像放在 Gtk::ScrolledWindow
中,然后再将其添加到window。如果不滚动,当您使 window 小于图像时,图像将不知道要渲染自己的哪一部分。
有一种方法可以在 window 及其内容之间添加一个层,该层由自定义容器组成,该容器位于父级 window 的首选大小左右。
这是我的重写 GtkFixed 解决了完全相同的问题:
reckless_fixed.h
#ifndef __RECKLESS_FIXED_H__
#define __RECKLESS_FIXED_H__
#ifndef NO_INCLUDE_WITHIN_HEADERS
#include <gtk/gtk.h>
#endif
#define RECKLESS_FIXED_TYPE (reckless_fixed_get_type ())
#define RECKLESS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RECKLESS_FIXED_TYPE, RecklessFixed))
#define RECKLESS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RECKLESS_FIXED_TYPE, RecklessFixedClass))
#define IS_RECKLESS_FIXED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RECKLESS_FIXED_TYPE))
#define IS_RECKLESS_FIXED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RECKLESS_FIXED_TYPE))
#define RECKLESS_FIXED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RECKLESS_FIXED_TYPE, RecklessFixedClass))
typedef struct _RecklessFixed RecklessFixed;
typedef struct _RecklessFixedClass RecklessFixedClass;
struct _RecklessFixed
{
GtkFixed container;
};
struct _RecklessFixedClass
{
GtkFixedClass container_class;
};
GType reckless_fixed_get_type(void);
GtkWidget* reckless_fixed_new(void);
static void reckless_fixed_get_preferred_width(GtkWidget *widget, int *minimal, int *natural);
static void reckless_fixed_get_preferred_height(GtkWidget *widget, int *minimal, int *natural);
#endif /* __RECKLESS_FIXED_H__ */
reckless_fixed.c
#include <gtk/gtk.h>
#include "reckless_fixed.h"
G_DEFINE_TYPE( RecklessFixed, reckless_fixed, GTK_TYPE_FIXED )
static void reckless_fixed_class_init( RecklessFixedClass* klass ) {
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
widget_class->get_preferred_width = reckless_fixed_get_preferred_width;
widget_class->get_preferred_height = reckless_fixed_get_preferred_height;
}
static void reckless_fixed_init( RecklessFixed* self ) {}
// here is where we are reckless about our content's size
static void reckless_fixed_get_preferred_width(GtkWidget *widget, int *minimal, int *natural) {
*minimal = *natural = 1;
}
//here too
static void reckless_fixed_get_preferred_height(GtkWidget *widget, int *minimal, int *natural) {
*minimal = *natural = 1;
}
GtkWidget* reckless_fixed_new (void) {
return g_object_new (RECKLESS_FIXED_TYPE, NULL);
}
请注意GTK版本-上面的例子适用于GTK-3.0。对于 <=2.0,存在 ::size-request 信号,通过连接和应答实现相同的目标。
此外,我会警告这种方法 - 仅在您完全确定自己在做什么以及为什么需要 content-independent window resize,因为这会破坏内置的 GTK 布局系统。