Окно с кнопкой
Этот пример демонстрирует, как создать окно верхнего уровня, установить его заголовок, размер и положение, как добавить кнопку в это окно и как связать сигналы с действиями.
Copy using Gtk ;
int main ( string [] args) {
Gtk . init ( ref args);
var window = new Window ();
window . title = "Первая GTK программа" ;
window . border_width = 10 ;
window . window_position = WindowPosition . CENTER ;
window . set_default_size ( 350 , 70 );
window . destroy . connect ( Gtk . main_quit );
var button = new Button . with_label ( "Нажми меня!" );
button . clicked . connect (() => {
button . label = "Спасибо!" ;
});
window . add (button);
window . show_all ();
Gtk . main ();
return 0 ;
}
Все классы GTK находятся внутри пространства имен Gtk . Вы должны инициализировать каждую программу GTK с помощью Gtk.init () .
Конечно при небольшом количестве подключенных пространств имен можно писать и просто init() без Gtk.
Скомпилируйте и запустите
Copy $ valac --pkg gtk+-3.0 gtk-hello.vala
$ ./gtk-hello
Настройка иконки приложения
Copy try {
// Либо прямо из файла ...
window . icon = new Gdk . Pixbuf . from_file ( "my-app.png" );
// ... или из темы
window . icon = IconTheme . get_default (). load_icon ( "my-app" , 48 , 0 );
} catch ( Error e) {
stderr . printf ( @"Не удалось загрузить значок приложения: $(e.message)" );
}
Синхронизация виджетов
Вы можете использовать сигналы чтобы синхронизировать значения виджетов. В этом примере ползунок и счетчик будут взаимосвязаны.
Copy using Gtk ;
public class SyncSample : Window {
private SpinButton spin_box;
private Scale slider;
public SyncSample () {
this . title = "Введите свой возраст" ;
this . window_position = WindowPosition . CENTER ;
this . destroy . connect ( Gtk . main_quit );
set_default_size ( 300 , 20 );
spin_box = new SpinButton . with_range ( 0 , 130 , 1 );
slider = new Scale . with_range ( Orientation . HORIZONTAL , 0 , 130 , 1 );
spin_box . adjustment . value_changed . connect (() => {
slider . adjustment . value = spin_box . adjustment . value ;
});
slider . adjustment . value_changed . connect (() => {
spin_box . adjustment . value = slider . adjustment . value ;
});
spin_box . adjustment . value = 35 ;
var hbox = new Box ( Orientation . HORIZONTAL , 5 );
hbox . homogeneous = true ;
hbox . add (spin_box);
hbox . add (slider);
add (hbox);
}
public static int main ( string [] args) {
Gtk . init ( ref args);
var window = new SyncSample ();
window . show_all ();
Gtk . main ();
return 0 ;
}
}
Панель инструментов, скроллинг текста и выбор файла
Простой просмотрщик текстовых файлов:
Copy using Gtk ;
public class TextFileViewer : Window {
private TextView text_view;
public TextFileViewer () {
this . title = "Просмотр текстовых файлов" ;
this . window_position = WindowPosition . CENTER ;
set_default_size ( 400 , 300 );
var toolbar = new Toolbar ();
toolbar . get_style_context (). add_class (STYLE_CLASS_PRIMARY_TOOLBAR);
var open_icon = new Gtk . Image . from_icon_name ( "document-open" ,
IconSize . SMALL_TOOLBAR );
var open_button = new Gtk . ToolButton (open_icon , "Open" );
open_button . is_important = true ;
toolbar . add (open_button);
open_button . clicked . connect (on_open_clicked);
this . text_view = new TextView ();
this . text_view . editable = false ;
this . text_view . cursor_visible = false ;
var scroll = new ScrolledWindow ( null , null );
scroll . set_policy ( PolicyType . AUTOMATIC , PolicyType . AUTOMATIC );
scroll . add ( this . text_view );
var vbox = new Box ( Orientation . VERTICAL , 0 );
vbox . pack_start (toolbar , false , true , 0 );
vbox . pack_start (scroll , true , true , 0 );
add (vbox);
}
private void on_open_clicked () {
var file_chooser = new FileChooserDialog ( "Open File" , this ,
FileChooserAction . OPEN ,
"_Cancel" , ResponseType . CANCEL ,
"_Open" , ResponseType . ACCEPT );
if ( file_chooser . run () == ResponseType . ACCEPT ) {
open_file ( file_chooser . get_filename ());
}
file_chooser . destroy ();
}
private void open_file ( string filename) {
try {
string text;
FileUtils . get_contents (filename , out text);
this . text_view . buffer . text = text;
} catch ( Error e) {
stderr . printf ( "Ошибка: %s\n" , e . message );
}
}
public static int main ( string [] args) {
Gtk . init ( ref args);
var window = new TextFileViewer ();
window . destroy . connect ( Gtk . main_quit );
window . show_all ();
Gtk . main ();
return 0 ;
}
}
Если вы хотите добавить дополнительные функции или изменить поведение диалога, вы можете создать подкласс FileChooserDialog . Например этот запоминает последнюю папку:
Copy using Gtk ;
public class OpenFileDialog : FileChooserDialog {
private string last_folder;
public OpenFileDialog () {
this . title = "Open File" ;
this . action = FileChooserAction . OPEN ;
add_button ( Stock . CANCEL , ResponseType . CANCEL );
add_button ( Stock . OPEN , ResponseType . ACCEPT );
set_default_response ( ResponseType . ACCEPT );
if ( this . last_folder != null ) {
set_current_folder ( this . last_folder );
}
}
public override void response ( int type) {
if (type == ResponseType . ACCEPT ) {
this . last_folder = get_current_folder ();
}
}
public static void main ( string [] args) {
Gtk . init ( ref args);
var ofd = new OpenFileDialog ();
if ( ofd . run () == ResponseType . OK ) {
stdout . printf ( "filename = %s\n" . printf ( ofd . get_filename ()));
}
}
}
Создание своего диалогового окна
Этот пример демонстрирует, как создать свой диалог, наследуясь от Dialog .
Copy using Gtk ;
public class SearchDialog : Dialog {
private Entry search_entry;
private CheckButton match_case;
private CheckButton find_backwards;
private Widget find_button;
public signal void find_next ( string text , bool case_sensitivity);
public signal void find_previous ( string text , bool case_sensitivity);
public SearchDialog () {
this . title = "Find" ;
this . border_width = 5 ;
set_default_size ( 350 , 100 );
create_widgets ();
connect_signals ();
}
private void create_widgets () {
// Create and setup widgets
this . search_entry = new Entry ();
var search_label = new Label . with_mnemonic ( "_Search for:" );
search_label . mnemonic_widget = this . search_entry ;
this . match_case = new CheckButton . with_mnemonic ( "_Match case" );
this . find_backwards = new CheckButton . with_mnemonic ( "Find _backwards" );
// Layout widgets
var hbox = new Box ( Orientation . HORIZONTAL , 20 );
hbox . pack_start (search_label , false , true , 0 );
hbox . pack_start ( this . search_entry , true , true , 0 );
var content = get_content_area () as Box ;
content . pack_start (hbox , false , true , 0 );
content . pack_start ( this . match_case , false , true , 0 );
content . pack_start ( this . find_backwards , false , true , 0 );
content . spacing = 10 ;
// Add buttons to button area at the bottom
add_button ( Stock . HELP , ResponseType . HELP );
add_button ( Stock . CLOSE , ResponseType . CLOSE );
this . find_button = add_button ( Stock . FIND , ResponseType . APPLY );
this . find_button . sensitive = false ;
show_all ();
}
private void connect_signals () {
this . search_entry . changed . connect (() => {
this . find_button . sensitive = ( this . search_entry . text != "" );
});
this . response . connect (on_response);
}
private void on_response ( Dialog source , int response_id) {
switch (response_id) {
case ResponseType . HELP :
// show_help ();
break ;
case ResponseType . APPLY :
on_find_clicked ();
break ;
case ResponseType . CLOSE :
destroy ();
break ;
}
}
private void on_find_clicked () {
string text = this . search_entry . text ;
bool cs = this . match_case . active ;
if ( this . find_backwards . active ) {
find_previous (text , cs);
} else {
find_next (text , cs);
}
}
}
int main ( string [] args) {
Gtk . init ( ref args);
var dialog = new SearchDialog ();
dialog . destroy . connect ( Gtk . main_quit );
dialog . show ();
Gtk . main ();
return 0 ;
}
Своё кастомное диалоговое окно гораздо проще создать не из кода а из Glade
Загрузка пользовательского интерфейса из файла XML
Вместо ручного кодирования пользовательского интерфейса вашего приложения вы можете создать его с помощью удобного конструктора пользовательского интерфейса, такого как Glade, и сохранить его в виде файла XML. Ваше приложение может загрузить пользовательский интерфейс из этого файла во время выполнения с помощью класса Gtk.Builder . Он может даже подключить все сигналы к их методам, если вы объявили их в Glade. Вот пример файла пользовательского интерфейса: sample.ui
Этот пример кода работает с файлом UI, связанным выше:
Copy using Gtk ;
public void on_button1_clicked ( Button source) {
source . label = "Thank you!" ;
}
public void on_button2_clicked ( Button source) {
source . label = "Thanks!" ;
}
int main ( string [] args) {
Gtk . init ( ref args);
try {
// Если UI содержит кастомные виджеты,они должны хотя бы один раз проинициализированы
// Type type = typeof(Foo.BarEntry);
// assert(type != 0);
var builder = new Builder ();
builder . add_from_file ( "sample.ui" );
builder . connect_signals ( null );
var window = builder . get_object ( "window" ) as Window ;
window . show_all ();
Gtk . main ();
} catch ( Error e) {
stderr . printf ( "Не получилось загрузить UI: %s\n" , e . message );
return 1 ;
}
return 0 ;
}
Подключение сигналов
...