原文:ZetCode
协议:CC BY-NC-SA 4.0
Ruby GTK 中的自定义小部件
原文: http://zetcode/gui/rubygtk/customwidget/
工具箱通常仅提供最常见的窗口小部件,例如按钮,文本窗口小部件,滑块等。没有工具箱可以提供所有可能的窗口小部件。 程序员必须自己创建此类小部件。 他们使用工具箱提供的绘图工具来完成此任务。 有两种可能:程序员可以修改或增强现有的小部件,或者可以从头开始创建自定义小部件。
刻录小部件
这是我们从头开始创建的小部件的示例。 可以在各种媒体刻录应用(例如 K3B)中找到此小部件。
custom.rb
#!/usr/bin/ruby
'''
ZetCode Ruby GTK tutorial
This example creates a custom widget.
Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''
require 'gtk3'
class Burning < Gtk::DrawingArea
def initialize parent
@parent = parent
super()
@num = [ "75", "150", "225", "300",
"375", "450", "525", "600", "675" ]
set_size_request 1, 30
signal_connect "draw" do
on_draw
end
end
def on_draw
cr = window.create_cairo_context
draw_widget cr
end
def draw_widget cr
cr.set_line_width 0.8
cr.select_font_face "Courier",
Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_NORMAL
cr.set_font_size 11
width = allocation.width
@cur_width = @parent.get_cur_value
step = (width / 10.0).round
till = (width / 750.0) * @cur_width
full = (width / 750.0) * 700
if @cur_width >= 700
cr.set_source_rgb 1.0, 1.0, 0.72
cr.rectangle 0, 0, full, 30
cr.clip
cr.paint
cr.reset_clip
cr.set_source_rgb 1.0, 0.68, 0.68
cr.rectangle full, 0, till-full, 30
cr.clip
cr.paint
cr.reset_clip
else
cr.set_source_rgb 1.0, 1.0, 0.72
cr.rectangle 0, 0, till, 30
cr.clip
cr.paint
cr.reset_clip
end
cr.set_source_rgb(0.35, 0.31, 0.24)
for i in 1..@num.length
cr.move_to i*step, 0
cr.line_to i*step, 5
cr.stroke
te = cr.text_extents @num[i-1]
cr.move_to i*step-te.width/2, 15
cr.text_path @num[i-1]
cr.stroke
end
end
end
class RubyApp < Gtk::Window
def initialize
super
set_title "Burning"
signal_connect "destroy" do
Gtk.main_quit
end
set_size_request 350, 200
set_window_position :center
@cur_value = 0
vbox = Gtk::Box.new :vertical, 2
scale = Gtk::Scale.new :horizontal
scale.set_range 0, 750
scale.set_digits 0
scale.set_size_request 160, 35
scale.set_value @cur_value
scale.signal_connect "value-changed" do |w|
on_changed w
end
fix = Gtk::Fixed.new
fix.put scale, 50, 50
vbox.pack_start fix
@burning = Burning.new self
vbox.pack_start @burning, :expand => false,
:fill => false, :padding => 0
add vbox
show_all
end
def on_changed widget
@cur_value = widget.value
@burning.queue_draw
end
def get_cur_value
return @cur_value
end
end
Gtk.init
window = RubyApp.new
Gtk.main
我们在窗口底部放置一个Gtk::DrawingArea
并手动绘制整个窗口小部件。 所有重要的代码都驻留在draw_widget
中,这是从 Burning 类的on_draw
方法调用的。 此小部件以图形方式显示介质的总容量和可用空间。 该小部件由比例小部件控制。 自定义窗口小部件的最小值为 0,最大值为 750。如果值达到 700,则开始绘制红色。 这通常表示过度燃烧。
@num = [ "75", "150", "225", "300",
"375", "450", "525", "600", "675" ]
这些数字显示在刻录小部件上。 它们显示了介质的容量。
@cur_width = @parent.get_cur_value
从父小部件中,我们获得了比例小部件的当前值。
till = (width / 750.0) * @cur_width
full = (width / 750.0) * 700
我们使用width
变量在小数位的值和自定义小部件的度量之间进行转换。 请注意,我们使用浮点值-在绘图中获得更高的精度。 till
参数确定要绘制的总大小。 该值来自滑块小部件。 它占整个面积的一部分。 full
参数确定我们开始绘制红色的点。
cr.set_source_rgb 1.0, 1.0, 0.72
cr.rectangle 0, 0, till, 30
cr.clip
cr.paint
cr.reset_clip
我们绘制一个黄色矩形,直到介质充满的地方。
te = cr.text_extents @num[i-1]
cr.move_to i*step-te.width/2, 15
cr.text_path @num[i-1]
cr.stroke
这里的代码在刻录小部件上绘制数字。 我们计算文本范围以正确定位文本。
def on_changed widget
@cur_value = widget.value
@burning.queue_draw
end
我们从小部件中获取值,并将其存储在@cur_value
变量中以备后用。 我们重新绘制刻录的小部件。
图:刻录小部件
在本章中,我们使用 GTK 和 Ruby 编程语言创建了一个自定义小部件。
Ruby GTK 中的贪食蛇
原文: http://zetcode/gui/rubygtk/nibbles/
在 Ruby GTK 编程教程的这一部分中,我们将创建一个贪食蛇游戏克隆。
贪食蛇是较旧的经典视频游戏。 它最初是在 70 年代后期创建的。 后来它被带到 PC 上。 在这个游戏中,玩家控制蛇。 目的是尽可能多地吃苹果。 蛇每次吃一个苹果,它的身体就会长大。 蛇必须避开墙壁和自己的身体。
开发
蛇的每个关节的大小为 10px。 蛇由光标键控制。 最初,蛇具有三个关节。 游戏立即开始。 游戏结束后,我们在窗口中心显示"Game Over"
消息。
board.rb
WIDTH = 300
HEIGHT = 270
DOT_SIZE = 10
ALL_DOTS = WIDTH * HEIGHT / (DOT_SIZE * DOT_SIZE)
RAND_POS = 26
DELAY = 100
$x = [0] * ALL_DOTS
$y = [0] * ALL_DOTS
class Board < Gtk::DrawingArea
def initialize
super
override_background_color :normal, Gdk::RGBA.new(0, 0, 0, 1)
signal_connect "draw" do
on_draw
end
init_game
end
def on_timer
if @inGame
check_apple
check_collision
move
queue_draw
return true
else
return false
end
end
def init_game
@left = false
@right = true
@up = false
@down = false
@inGame = true
@dots = 3
for i in 0..@dots
$x[i] = 50 - i * 10
$y[i] = 50
end
begin
@dot = Cairo::ImageSurface.from_png "dot.png"
@head = Cairo::ImageSurface.from_png "head.png"
@apple = Cairo::ImageSurface.from_png "apple.png"
rescue Exception => e
puts "cannot load images"
exit
end
locate_apple
GLib::Timeout.add(DELAY) { on_timer }
end
def on_draw
cr = window.create_cairo_context
if @inGame
draw_objects cr
else
game_over cr
end
end
def draw_objects cr
cr.set_source_rgb 0, 0, 0
cr.paint
cr.set_source @apple, @apple_x, @apple_y
cr.paint
for z in 0..@dots
if z == 0
cr.set_source @head, $x[z], $y[z]
cr.paint
else
cr.set_source @dot, $x[z], $y[z]
cr.paint
end
end
end
def game_over cr
w = allocation.width / 2
h = allocation.height / 2
cr.set_font_size 15
te = cr.text_extents "Game Over"
cr.set_source_rgb 65535, 65535, 65535
cr.move_to w - te.width/2, h
cr.show_text "Game Over"
end
def check_apple
if $x[0] == @apple_x and $y[0] == @apple_y
@dots = @dots + 1
locate_apple
end
end
def move
z = @dots
while z > 0
$x[z] = $x[(z - 1)]
$y[z] = $y[(z - 1)]
z = z - 1
end
if @left
$x[0] -= DOT_SIZE
end
if @right
$x[0] += DOT_SIZE
end
if @up
$y[0] -= DOT_SIZE
end
if @down
$y[0] += DOT_SIZE
end
end
def check_collision
z = @dots
while z > 0
if z > 4 and $x[0] == $x[z] and $y[0] == $y[z]
@inGame = false
end
z = z - 1
end
if $y[0] > HEIGHT - DOT_SIZE
@inGame = false
end
if $y[0] < 0
@inGame = false
end
if $x[0] > WIDTH - DOT_SIZE
@inGame = false
end
if $x[0] < 0
@inGame = false
end
end
def locate_apple
r = rand RAND_POS
@apple_x = r * DOT_SIZE
r = rand RAND_POS
@apple_y = r * DOT_SIZE
end
def on_key_down event
key = event.keyval
if key == Gdk::Keyval::GDK_KEY_Left and not @right
@left = true
@up = false
@down = false
end
if key == Gdk::Keyval::GDK_KEY_Right and not @left
@right = true
@up = false
@down = false
end
if key == Gdk::Keyval::GDK_KEY_Up and not @down
@up = true
@right = false
@left = false
end
if key == Gdk::Keyval::GDK_KEY_Down and not @up
@down = true
@right = false
@left = false
end
end
end
首先,我们将定义一些在游戏中使用的全局变量。 WIDTH
和HEIGHT
常数确定Board
的大小。 DOT_SIZE
是苹果的大小和蛇的点。 ALL_DOTS
常数定义Board
上可能的最大点数。 RAND_POS
常数用于计算苹果的随机位置。 DELAY
常数确定游戏的速度。
$x = [0] * ALL_DOTS
$y = [0] * ALL_DOTS
这两个数组存储蛇的所有可能关节的 x,y 坐标。
init_game
方法初始化游戏。
@left = false
@right = true
@up = false
@down = false
@inGame = true
@dots = 3
我们初始化我们在游戏中使用的变量。
for i in 0..@dots
$x[i] = 50 - i * 10
$y[i] = 50
end
我们给蛇关节初始坐标。 它总是从同一位置开始。
begin
@dot = Cairo::ImageSurface.from_png "dot.png"
@head = Cairo::ImageSurface.from_png "head.png"
@apple = Cairo::ImageSurface.from_png "apple.png"
rescue Exception => e
puts "cannot load images"
exit
end
加载了必要的图像。
locate_apple
苹果进入初始随机位置。
GLib::Timeout.add(DELAY) { on_timer }
GLib::Timeout.add
方法将on_timer
方法设置为每DELAY
毫秒调用一次。
if @inGame
draw_objects cr
else
game_over cr
end
在on_draw
方法内部,我们检查@inGame
变量。 如果是真的,我们绘制对象:苹果和蛇关节。 否则,我们显示"Game Over"
文本。
def draw_objects cr
cr.set_source_rgb 0, 0, 0
cr.paint
cr.set_source @apple, @apple_x, @apple_y
cr.paint
for z in 0..@dots
if z == 0
cr.set_source @head, $x[z], $y[z]
cr.paint
else
cr.set_source @dot, $x[z], $y[z]
cr.paint
end
end
end
draw_objects
方法绘制苹果和蛇的关节。 蛇的第一个关节是其头部,用红色圆圈表示。
def check_apple
if $x[0] == @apple_x and $y[0] == @apple_y
@dots = @dots + 1
locate_apple
end
end
check_apple
方法检查蛇是否击中了苹果对象。 如果是这样,我们添加另一个蛇形关节并调用locate_apple
方法,该方法随机放置一个新的Apple
对象。
在move
方法中,我们有游戏的关键算法。 要了解它,我们需要看看蛇是如何运动的。 我们控制蛇的头。 我们可以使用光标键更改其方向。 其余关节在链上向上移动一个位置。 第二关节移动到第一个关节的位置,第三关节移动到第二个关节的位置,依此类推。
while z > 0
$x[z] = $x[(z - 1)]
$y[z] = $y[(z - 1)]
z = z - 1
end
该代码将关节向上移动。
if @left
$x[0] -= DOT_SIZE
end
如果向左移动,则磁头向左移动。
在check_collision
方法中,我们确定蛇是否击中了自己或撞墙之一。
while z > 0
if z > 4 and $x[0] == $x[z] and $y[0] == $y[z]
@inGame = false
end
z = z - 1
end
如果蛇用头撞到关节之一,我们就结束游戏。
if $y[0] > HEIGHT - DOT_SIZE
@inGame = false
end
如果蛇击中了棋盘的底部,则游戏结束。
locate_apple
方法在板上随机放置一个苹果。
r = rand RAND_POS
我们得到一个从 0 到RAND_POS-1
的随机数。
@apple_x = r * DOT_SIZE
...
@apple_y = r * DOT_SIZE
这些行设置了apple
对象的 x,y 坐标。
if @inGame
check_apple
check_collision
move
queue_draw
return true
else
return false
end
每DELAY
ms 会调用一次on_timer
方法。 如果我们参与了游戏,我们将调用三种构建游戏逻辑的方法。 否则,我们返回false
,它将停止计时器事件。
在Board
类的on_key_down
方法中,我们确定按下的键。
if key == Gdk::Keyval::GDK_KEY_Left and not @right
@left = true
@up = false
@down = false
end
如果单击左光标键,则将left
变量设置为true
。 在move
方法中使用此变量来更改蛇对象的坐标。 还要注意,当蛇向右行驶时,我们不能立即向左转。
nibbles.rb
#!/usr/bin/ruby
'''
ZetCode Ruby GTK tutorial
This is a simple Nibbles game
clone.
Author: Jan Bodnar
Website: www.zetcode.com
Last modified: May 2014
'''
require 'gtk3'
require './board'
class RubyApp < Gtk::Window
def initialize
super
set_title "Nibbles"
signal_connect "destroy" do
Gtk.main_quit
end
@board = Board.new
signal_connect "key-press-event" do |w, e|
on_key_down w, e
end
add @board
set_default_size WIDTH, HEIGHT
set_window_position :center
show_all
end
def on_key_down widget, event
key = event.keyval
@board.on_key_down event
end
end
Gtk.init
window = RubyApp.new
Gtk.main
在这个类中,我们设置了贪食蛇游戏。
def on_key_down widget, event
key = event.keyval
@board.on_key_down event
end
我们捕获按键事件,并将处理委托给电路板类的on_key_down
方法。
图:贪食蛇
这是使用 GTK 库和 Ruby 编程语言编程的贪食蛇电脑游戏。
GTK# 教程
原文: http://zetcode/gui/gtksharp/
这是针对 C# 编程语言的 GTK# 教程。 本教程适合初学者和更高级的程序员。
目录
- 简介
- 第一步
- 布局管理
- 菜单
- 工具栏
- 事件
- 小部件
- 小部件 II
- 高级小部件
- 对话框
- Pango
- 使用 Cario 绘图
- 使用 cairo II 绘制
- 自定义小部件
GTK#
GTK# 是针对 C# 编程语言的 GTK+ 的包装。 该库有助于使用 Mono 或任何其他兼容的 CLR 构建图形 GNOME 应用。 使用 Gtk# 构建的应用将在许多平台上运行,包括 Linux,Microsoft Windows 和 Mac OSX。GTK# 是 Mono 计划的一部分。
Tweet
相关教程
C# 教程深入介绍了 C# 语言。 Mono C# Winforms 教程和 C# Qyoto 教程提供了 C# 语言的替代 GUI 工具箱。
GTK# 简介
原文: http://zetcode/gui/gtksharp/introduction/
这是 GTK# 编程入门教程。 本教程针对 C# 编程语言。 它已在 Linux 上创建并经过测试。 GTK# 编程教程适合新手和中级程序员。 这是本教程中使用的图像。
GTK+
GTK+ 是用于创建图形用户界面的库。 该库是用 C 编程语言创建的。 GTK+ 库也称为 GIMP 工具包。 最初,该库是在开发 GIMP 图像处理器时创建的。 从那时起,GTK+ 成为 Linux 和 BSD Unix 下最受欢迎的工具包之一。 如今,开源世界中的大多数 GUI 软件都是在 Qt 或 GTK+ 中创建的。 GTK+ 是面向对象的应用编程接口。 面向对象的系统是使用 Glib 对象系统创建的,该系统是 GTK+ 库的基础。 GObject
还可以为其他各种编程语言创建语言绑定。 存在用于 C++ ,Python,Perl,Java,C# 和其他编程语言的语言绑定。
GTK+ 本身取决于以下库。
- Glib
- Pango
- ATK
- GDK
- GdkPixbuf
- Cario
Glib
是通用工具库。 它提供各种数据类型,字符串工具,启用错误报告,消息日志记录,使用线程和其他有用的编程功能。 Pango
是一个使国际化的库。 ATK
是辅助功能工具包。 该工具包提供的工具可帮助残障人士使用计算机。 GDK
是底层图形系统提供的低级绘图和窗口功能的包装。 在 Linux 上,GDK 位于 X Server 和 GTK+ 库之间。 最近,它的许多功能已委托给 Cario 库。 GdkPixbuf
库是用于图像加载和像素缓冲区操作的工具包。 Cario 是用于创建 2D 矢量图形的库。 自 2.8 版起,它已包含在 GTK+ 中。
Gnome 和 XFce 桌面环境已使用 GTK+ 库创建。 SWT 和 wxWidgets 是使用 GTK+ 的众所周知的编程框架。 使用 GTK+ 的著名软件应用包括 Firefox 或 Inkscape。
GTK#
GTK# 是针对 C# 编程语言的 GTK+ 的包装。 该库有助于使用 Mono 或任何其他兼容的 CLR 构建图形 GNOME 应用。 Gtk# 是一个事件驱动的系统,就像任何其他现代的窗口库一样,其中应用中的每个小部件都具有处理器方法,这些处理器方法在发生特定事件时被调用。 使用 Gtk# 构建的应用将在许多平台上运行,包括 Linux,Microsoft,Windows 和 Mac OSX。GTK# 是 Mono 计划的一部分。 Mono 中基本上有两个窗口小部件工具箱:Winforms 和 GTK# 。 GTK# 被认为是 Linux/Unix 操作系统的本机。
编译 GTK# 应用
我们使用 gmcs 编译器来编译我们的 GTK# 应用。
$ gmcs -pkg:gtk-sharp-2.0 -r:/usr/lib/mono/2.0/Mono.Cairo.dll application.cs
上一行编译了一个也使用 Cario 库的 GTK# 应用。
数据来源
- go-mono
- wikipedia
在 GTK# 教程的这一部分中,我们介绍了 GTK# 库。
PyQt5 中的布局管理
原文: http://zetcode/gui/pyqt5/layout/
布局管理是我们将小部件放置在应用窗口中的方式。 我们可以使用绝对定位或布局类放置小部件。 使用布局管理器管理布局是组织窗口小部件的首选方式。
绝对定位
程序员以像素为单位指定每个小部件的位置和大小。 使用绝对定位时,我们必须了解以下限制:
- 如果我们调整窗口大小,则小部件的大小和位置不会改变
- 在各种平台上,应用看起来可能有所不同
- 在我们的应用中更改字体可能会破坏布局
- 如果我们决定更改布局,则必须完全重做布局,这既繁琐又耗时
以下示例将小部件放置在绝对坐标中。
absolute.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
This example shows three labels on a window
using absolute positioning.
Author: Jan Bodnar
Website: zetcode
Last edited: August 2017
"""
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
lbl1 = QLabel('Zetcode', self)
lbl1.move(15, 10)
lbl2 = QLabel('tutorials', self)
lbl2.move(35, 40)
lbl3 = QLabel('for programmers', self)
lbl3.move(55, 70)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Absolute')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
我们使用move()
方法定位小部件。 在我们的例子中,这些是标签。 我们通过提供 x 和 y 坐标来定位它们。 坐标系的起点在左上角。 x 值从左到右增长。 y 值从上到下增长。
lbl1 = QLabel('Zetcode', self)
lbl1.move(15, 10)
标签窗口小部件位于x=15
和y=10
处。
图:绝对定位
盒子布局
QHBoxLayout
和QVBoxLayout
是在水平和垂直方向排列小部件的基本布局类。
想象一下,我们想在右下角放置两个按钮。 为了创建这样的布局,我们使用一个水平框和一个垂直框。 为了创建必要的空间,我们添加了拉伸因子。
buttons.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
In this example, we position two push
buttons in the bottom-right corner
of the window.
Author: Jan Bodnar
Website: zetcode
Last edited: August 2017
"""
import sys
from PyQt5.QtWidgets import (QWidget, QPushButton,
QHBoxLayout, QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
self.setGeometry(300, 300, 300, 150)
self.setWindowTitle('Buttons')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
该示例在窗口的右下角放置了两个按钮。 当我们调整应用窗口的大小时,它们会停留在该位置。 我们同时使用HBoxLayout
和QVBoxLayout
。
okButton = QPushButton("OK")
cancelButton = QPushButton("Cancel")
在这里,我们创建两个按钮。
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(okButton)
hbox.addWidget(cancelButton)
我们创建一个水平框布局,并添加一个拉伸因子和两个按钮。 拉伸在两个按钮之前增加了可拉伸的空间。 这会将它们推到窗口的右侧。
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
将水平布局放置在垂直布局中。 垂直框中的拉伸因子会将带有按钮的水平框推到窗口底部。
self.setLayout(vbox)
最后,我们设置窗口的主要布局。
图:按钮
QGridLayout
QGridLayout
是最通用的布局类。 它将空间分为行和列。
calculator.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
In this example, we create a skeleton
of a calculator using QGridLayout.
Author: Jan Bodnar
Website: zetcode
Last edited: August 2017
"""
import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout,
QPushButton, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
grid = QGridLayout()
self.setLayout(grid)
names = ['Cls', 'Bck', '', 'Close',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+']
positions = [(i,j) for i in range(5) for j in range(4)]
for position, name in zip(positions, names):
if name == '':
continue
button = QPushButton(name)
grid.addWidget(button, *position)
self.move(300, 150)
self.setWindowTitle('Calculator')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在我们的示例中,我们创建了一个按钮网格。
grid = QGridLayout()
self.setLayout(grid)
创建QGridLayout
的实例,并将其设置为应用窗口的布局。
names = ['Cls', 'Bck', '', 'Close',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', '=', '+']
这些是稍后用于按钮的标签。
positions = [(i,j) for i in range(5) for j in range(4)]
我们在网格中创建位置列表。
for position, name in zip(positions, names):
if name == '':
continue
button = QPushButton(name)
grid.addWidget(button, *position)
使用addWidget()
方法创建按钮并将其添加到布局。
图:计算机骨架
回顾示例
小部件可以跨越网格中的多个列或行。 在下一个示例中,我们将对此进行说明。
review.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
ZetCode PyQt5 tutorial
In this example, we create a bit
more complicated window layout using
the QGridLayout manager.
author: Jan Bodnar
website: zetcode
last edited: January 2015
"""
import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit,
QTextEdit, QGridLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
title = QLabel('Title')
author = QLabel('Author')
review = QLabel('Review')
titleEdit = QLineEdit()
authorEdit = QLineEdit()
reviewEdit = QTextEdit()
grid = QGridLayout()
grid.setSpacing(10)
grid.addWidget(title, 1, 0)
grid.addWidget(titleEdit, 1, 1)
grid.addWidget(author, 2, 0)
grid.addWidget(authorEdit, 2, 1)
grid.addWidget(review, 3, 0)
grid.addWidget(reviewEdit, 3, 1, 5, 1)
self.setLayout(grid)
self.setGeometry(300, 300, 350, 300)
self.setWindowTitle('Review')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
我们创建一个窗口,其中有三个标签,两个行编辑和一个文本编辑小部件。 使用QGridLayout
完成布局。
grid = QGridLayout()
grid.setSpacing(10)
我们创建网格布局并设置小部件之间的间距。
grid.addWidget(reviewEdit, 3, 1, 5, 1)
如果我们将小部件添加到网格,则可以提供小部件的行跨度和列跨度。 在我们的例子中,我们使reviewEdit
小部件跨越 5 行。
图:回顾 example
PyQt5 教程的这一部分专门用于布局管理。
GTK 的第一步
原文: http://zetcode/gui/gtksharp/firststeps/
在 GTK# 编程教程的这一部分中,我们将进行编程的第一步。 我们将创建简单的程序。
简单的例子
第一个代码示例是一个简单的示例,它显示了居中的窗口。
center.cs
using Gtk;
class SharpApp : Window {
public SharpApp() : base("Center")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
Show();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
该代码示例在屏幕中央显示一个小窗口。
$ gmcs -pkg:gtk-sharp-2.0 center.cs
这是我们编译代码示例的方式。
using Gtk;
现在,我们可以直接使用Gtk
名称空间中的对象。 我们可以写Window
而不是Gtk.Window
。
class SharpApp : Window {
我们的应用基于SharpApp
类。 该类继承自Window
类。
public SharpApp() : base("Center")
{
...
}
这是构造器。 它构建了我们的应用。 它还通过base()
关键字调用其父构造器。
SetDefaultSize(250, 200);
这行为我们的窗口设置默认大小。
SetPosition(WindowPosition.Center);
这条线使窗口在屏幕上居中。
DeleteEvent += delegate { Application.Quit(); };
我们将一个代理插入DeleteEvent
。 当我们单击标题栏中的关闭按钮时,将触发此事件。 或按 Alt + F4
。 我们的代表永久退出了申请。
Show();
现在我们显示窗口。 在调用Show()
方法之前,该窗口不可见。
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
Main()
方法是应用的入口点。 它启动并运行程序。
图标
在下一个示例中,我们显示应用图标。 大多数窗口管理器在标题栏的左上角以及任务栏上都显示图标。
icon.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Icon")
{
SetDefaultSize(250, 160);
SetPosition(WindowPosition.Center);
SetIconFromFile("web.png");
DeleteEvent += new DeleteEventHandler(OnDelete);
Show();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
void OnDelete(object obj, DeleteEventArgs args)
{
Application.Quit();
}
}
该代码示例显示了应用图标。
SetIconFromFile("web.png");
SetIconFromFile()
方法为窗口设置图标。 从当前工作目录中的磁盘加载映像。
DeleteEvent += new DeleteEventHandler(OnDelete);
这是另一种方式,我们如何将事件处理器插入事件。 只是有点冗长。
void OnDelete(object obj, DeleteEventArgs args)
{
Application.Quit();
}
这是删除事件的事件处理器。
图:图标
按钮
在下一个示例中,我们将使用 GTK# 库进一步增强我们的编程技能。
buttons.cs
using Gtk;
class SharpApp : Window
{
public SharpApp() : base("Buttons")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
Fixed fix = new Fixed();
Button btn1 = new Button("Button");
btn1.Sensitive = false;
Button btn2 = new Button("Button");
Button btn3 = new Button(Stock.Close);
Button btn4 = new Button("Button");
btn4.SetSizeRequest(80, 40);
fix.Put(btn1, 20, 30);
fix.Put(btn2, 100, 30);
fix.Put(btn3, 20, 80);
fix.Put(btn4, 100, 80);
Add(fix);
ShowAll();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
我们在窗口上显示四个不同的按钮。 我们将看到容器窗口小部件和子窗口小部件之间的区别,并将更改子窗口小部件的某些属性。
Fixed fix = new Fixed();
Fixed
小部件是不可见的容器小部件。 其目的是包含其他子窗口小部件。
Button btn1 = new Button("Button");
Button
是子窗口小部件。 子窗口小部件放置在容器内。
btn1.Sensitive = false;
我们使此按钮不敏感。 这意味着我们无法单击它。 图形化的小部件为灰色。
Button btn3 = new Button(Stock.Close);
第三个按钮在其区域内显示图像。 GTK# 库具有我们可以使用的内置图像库。
btn4.SetSizeRequest(80, 40);
在这里,我们更改按钮的大小。
fix.Put(btn1, 20, 30);
fix.Put(btn2, 100, 30);
...
在这里,我们将按钮小部件放置在固定容器小部件内。
Add(fix);
我们将Fixed
容器设置为Window
小部件的主要容器。
ShowAll();
我们可以调用ShowAll()
方法,也可以在每个小部件上调用Show()
方法。 包括容器。
图:按钮
在本章中,我们在 GTK# 编程库中创建了第一个程序。
GTK# 中的布局管理
原文: http://zetcode/gui/gtksharp/layout/
在本章中,我们将展示如何在窗口或对话框中布置窗口小部件。
在设计应用的 GUI 时,我们决定要使用哪些小部件以及如何在应用中组织这些小部件。 为了组织窗口小部件,我们使用专门的不可见窗口小部件,称为布局容器。 在本章中,我们将提到Alignment
,Fixed
,VBox
和Table
。
Fixed
Fixed
容器将子窗口小部件放置在固定位置并具有固定大小。 此容器不执行自动布局管理。 在大多数应用中,我们不使用此容器。 我们在某些专业领域使用它。 例如游戏,使用图表的专用应用,可以移动的可调整大小的组件(如电子表格应用中的图表),小型教育示例。
fixed.cs
using Gtk;
using System;
class SharpApp : Window {
private Gdk.Pixbuf rotunda;
private Gdk.Pixbuf bardejov;
private Gdk.Pixbuf mincol;
public SharpApp() : base("Fixed")
{
SetDefaultSize(300, 280);
SetPosition(WindowPosition.Center);
ModifyBg(StateType.Normal, new Gdk.Color(40, 40, 40));
DeleteEvent += delegate { Application.Quit(); };
try {
bardejov = new Gdk.Pixbuf("bardejov.jpg");
rotunda = new Gdk.Pixbuf("rotunda.jpg");
mincol = new Gdk.Pixbuf("mincol.jpg");
} catch {
Console.WriteLine("Images not found");
Environment.Exit(1);
}
Image image1 = new Image(bardejov);
Image image2 = new Image(rotunda);
Image image3 = new Image(mincol);
Fixed fix = new Fixed();
fix.Put(image1, 20, 20);
fix.Put(image2, 40, 160);
fix.Put(image3, 170, 50);
Add(fix);
ShowAll();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
在我们的示例中,我们在窗口上显示了三个小图像。 我们明确指定放置这些图像的 x,y 坐标。
ModifyBg(StateType.Normal, new Gdk.Color(40, 40, 40));
为了获得更好的视觉体验,我们将背景色更改为深灰色。
bardejov = new Gdk.Pixbuf("bardejov.jpg");
我们将图像从磁盘加载到Gdk.Pixbuf
对象。
Image image1 = new Image(bardejov);
Image image2 = new Image(rotunda);
Image image3 = new Image(mincol);
Image
是用于显示图像的小部件。 它在构造器中使用Gdk.Pixbuf
对象。
Fixed fix = new Fixed();
我们创建Fixed
容器。
fix.Put(image1, 20, 20);
我们将第一个图像放置在x = 20
,y = 20
坐标处。
Add(fix);
最后,我们将Fixed
容器添加到窗口中。
图:固定
Alignment
Alignment
容器控制其子窗口小部件的对齐方式和大小。
alignment.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Alignment")
{
SetDefaultSize(260, 150);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
VBox vbox = new VBox(false, 5);
HBox hbox = new HBox(true, 3);
Alignment valign = new Alignment(0, 1, 0, 0);
vbox.PackStart(valign);
Button ok = new Button("OK");
ok.SetSizeRequest(70, 30);
Button close = new Button("Close");
hbox.Add(ok);
hbox.Add(close);
Alignment halign = new Alignment(1, 0, 0, 0);
halign.Add(hbox);
vbox.PackStart(halign, false, false, 3);
Add(vbox);
ShowAll();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
在代码示例中,我们在窗口的右下角放置了两个按钮。 为此,我们使用一个水平框和一个垂直框以及两个对齐容器。
Alignment valign = new Alignment(0, 1, 0, 0);
这会将子窗口小部件置于底部。
vbox.PackStart(valign);
在这里,我们将Alignment
小部件放置到垂直框中。
HBox hbox = new HBox(true, 3);
...
Button ok = new Button("OK");
ok.SetSizeRequest(70, 30);
Button close = new Button("Close");
hbox.Add(ok);
hbox.Add(close);
我们创建一个水平框,并在其中放置两个按钮。
Alignment halign = new Alignment(1, 0, 0, 0);
halign.Add(hbox);
vbox.PackStart(halign, false, false, 3);
这将创建一个对齐容器,它将其子窗口小部件放在右侧。 我们将水平框添加到对齐容器中,然后将对齐容器包装到垂直框中。 我们必须记住,对齐容器仅包含一个子窗口小部件。 这就是为什么我们必须使用盒子。
图:对齐
Table
Table
小部件按行和列排列小部件。
calculator.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Calculator")
{
SetDefaultSize(250, 230);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
VBox vbox = new VBox(false, 2);
MenuBar mb = new MenuBar();
Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;
mb.Append(file);
vbox.PackStart(mb, false, false, 0);
Table table = new Table(5, 4, true);
table.Attach(new Button("Cls"), 0, 1, 0, 1);
table.Attach(new Button("Bck"), 1, 2, 0, 1);
table.Attach(new Label(), 2, 3, 0, 1);
table.Attach(new Button("Close"), 3, 4, 0, 1);
table.Attach(new Button("7"), 0, 1, 1, 2);
table.Attach(new Button("8"), 1, 2, 1, 2);
table.Attach(new Button("9"), 2, 3, 1, 2);
table.Attach(new Button("/"), 3, 4, 1, 2);
table.Attach(new Button("4"), 0, 1, 2, 3);
table.Attach(new Button("5"), 1, 2, 2, 3);
table.Attach(new Button("6"), 2, 3, 2, 3);
table.Attach(new Button("*"), 3, 4, 2, 3);
table.Attach(new Button("1"), 0, 1, 3, 4);
table.Attach(new Button("2"), 1, 2, 3, 4);
table.Attach(new Button("3"), 2, 3, 3, 4);
table.Attach(new Button("-"), 3, 4, 3, 4);
table.Attach(new Button("0"), 0, 1, 4, 5);
table.Attach(new Button("."), 1, 2, 4, 5);
table.Attach(new Button("="), 2, 3, 4, 5);
table.Attach(new Button("+"), 3, 4, 4, 5);
vbox.PackStart(new Entry(), false, false, 0);
vbox.PackEnd(table, true, true, 0);
Add(vbox);
ShowAll();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
我们使用Table
小部件创建一个计算器框架。
Table table = new Table(5, 4, true);
我们创建一个具有 5 行 4 列的表小部件。 第三个参数是齐次参数。 如果设置为true
,则表中的所有小部件都具有相同的大小。 所有窗口小部件的大小等于表容器中最大的窗口小部件。
table.Attach(new Button("Cls"), 0, 1, 0, 1);
我们在表格容器上附加一个按钮。 到表格的左上方单元格。 前两个参数是单元格的左侧和右侧,后两个参数是单元格的顶部和左侧。
vbox.PackEnd(table, true, true, 0);
我们将表格小部件打包到垂直框中。
图:计算机骨架
窗口
接下来,我们将创建一个更高级的示例。 我们显示一个窗口,可以在 JDeveloper IDE 中找到它。
windows.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Windows")
{
SetDefaultSize(300, 250);
SetPosition(WindowPosition.Center);
BorderWidth = 15;
DeleteEvent += delegate { Application.Quit(); };
Table table = new Table(8, 4, false);
table.ColumnSpacing = 3;
Label title = new Label("Windows");
Alignment halign = new Alignment(0, 0, 0, 0);
halign.Add(title);
table.Attach(halign, 0, 1, 0, 1, AttachOptions.Fill,
AttachOptions.Fill, 0, 0);
TextView wins = new TextView();
wins.ModifyFg(StateType.Normal, new Gdk.Color(20, 20, 20));
wins.CursorVisible = false;
table.Attach(wins, 0, 2, 1, 3, AttachOptions.Fill | AttachOptions.Expand,
AttachOptions.Fill | AttachOptions.Expand, 1, 1);
Button activate = new Button("Activate");
activate.SetSizeRequest(50, 30);
table.Attach(activate, 3, 4, 1, 2, AttachOptions.Fill,
AttachOptions.Shrink, 1, 1);
Alignment valign = new Alignment(0, 0, 0, 0);
Button close = new Button("Close");
close.SetSizeRequest(70, 30);
valign.Add(close);
table.SetRowSpacing(1, 3);
table.Attach(valign, 3, 4, 2, 3, AttachOptions.Fill,
AttachOptions.Fill | AttachOptions.Expand, 1, 1);
Alignment halign2 = new Alignment(0, 1, 0, 0);
Button help = new Button("Help");
help.SetSizeRequest(70, 30);
halign2.Add(help);
table.SetRowSpacing(3, 6);
table.Attach(halign2, 0, 1, 4, 5, AttachOptions.Fill,
AttachOptions.Fill, 0, 0);
Button ok = new Button("OK");
ok.SetSizeRequest(70, 30);
table.Attach(ok, 3, 4, 4, 5, AttachOptions.Fill,
AttachOptions.Fill, 0, 0);
Add(table);
ShowAll();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
该代码示例显示了如何在 GTK# 中创建类似的窗口。
Table table = new Table(8, 4, false);
table.ColumnSpacing = 3;
该示例基于Table
容器。 列之间将有 3px 的间距。
Label title = new Label("Windows");
Alignment halign = new Alignment(0, 0, 0, 0);
halign.Add(title);
table.Attach(halign, 0, 1, 0, 1, AttachOptions.Fill,
AttachOptions.Fill, 0, 0);
这段代码创建了一个向左对齐的标签。 标签放置在Table
容器的第一行中。
TextView wins = new TextView();
wins.ModifyFg(StateType.Normal, new Gdk.Color(20, 20, 20));
wins.CursorVisible = false;
table.Attach(wins, 0, 2, 1, 3, AttachOptions.Fill | AttachOptions.Expand,
AttachOptions.Fill | AttachOptions.Expand, 1, 1);
文本视图小部件跨越两行两列。 我们使小部件不可编辑并隐藏光标。
Alignment valign = new Alignment(0, 0, 0, 0);
Button close = new Button("Close");
close.SetSizeRequest(70, 30);
valign.Add(close);
table.SetRowSpacing(1, 3);
table.Attach(valign, 3, 4, 2, 3, AttachOptions.Fill,
AttachOptions.Fill | AttachOptions.Expand, 1, 1);
我们将关闭按钮放在文本视图小部件旁边的第四列中。 (我们从零开始计数)将按钮添加到对齐小部件中,以便可以将其对齐到顶部。
图:窗口
在本章中,我们介绍了 GTK# 小部件的布局管理。
GTK 中的菜单
原文: http://zetcode/gui/gtksharp/menus/
在 GTK# 编程教程的这一部分中,我们将使用菜单。
菜单栏是 GUI 应用中最常见的部分之一。 它是位于各个菜单中的一组命令。 在控制台应用中,我们必须记住各种奥术命令,而在这里,我们将大多数命令分组为逻辑部分。 这些公认的标准可进一步减少学习新应用的时间。
简单菜单
在第一个示例中,我们将创建一个带有一个文件菜单的菜单栏。 该菜单将只有一个菜单项。 通过选择项目,应用退出。
simplemenu.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Simple menu")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
MenuBar mb = new MenuBar();
Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;
MenuItem exit = new MenuItem("Exit");
exit.Activated += OnActivated;
filemenu.Append(exit);
mb.Append(file);
VBox vbox = new VBox(false, 2);
vbox.PackStart(mb, false, false, 0);
Add(vbox);
ShowAll();
}
void OnActivated(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
这是一个最小的菜单栏功能示例。
MenuBar mb = new MenuBar();
MenuBar
小部件已创建。
Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;
创建顶层MenuItem
。
MenuItem exit = new MenuItem("Exit");
exit.Activated += OnActivated;
filemenu.Append(exit);
将创建出口MenuItem
,并将其附加到文件MenuItem
中。
mb.Append(file);
顶级MenuItem
被附加到MenuBar
小部件。
VBox vbox = new VBox(false, 2);
vbox.PackStart(mb, false, false, 0);
与其他工具包不同,我们必须自己照顾布局管理。 我们将菜单栏放入垂直框中。
图:简单菜单
图像菜单
在下一个示例中,我们将进一步探索菜单。 我们将图像和加速器添加到我们的菜单项中。 加速器是用于激活菜单项的键盘快捷键。
imagemenu.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Image menu")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
MenuBar mb = new MenuBar();
Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;
AccelGroup agr = new AccelGroup();
AddAccelGroup(agr);
ImageMenuItem newi = new ImageMenuItem(Stock.New, agr);
newi.AddAccelerator("activate", agr, new AccelKey(
Gdk.Key.n, Gdk.ModifierType.ControlMask, AccelFlags.Visible));
filemenu.Append(newi);
ImageMenuItem open = new ImageMenuItem(Stock.Open, agr);
open.AddAccelerator("activate", agr, new AccelKey(
Gdk.Key.n, Gdk.ModifierType.ControlMask, AccelFlags.Visible));
filemenu.Append(open);
SeparatorMenuItem sep = new SeparatorMenuItem();
filemenu.Append(sep);
ImageMenuItem exit = new ImageMenuItem(Stock.Quit, agr);
exit.AddAccelerator("activate", agr, new AccelKey(
Gdk.Key.q, Gdk.ModifierType.ControlMask, AccelFlags.Visible));
exit.Activated += OnActivated;
filemenu.Append(exit);
mb.Append(file);
VBox vbox = new VBox(false, 2);
vbox.PackStart(mb, false, false, 0);
vbox.PackStart(new Label(), false, false, 0);
Add(vbox);
ShowAll();
}
void OnActivated(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
我们的示例显示了具有三个子菜单项的顶级菜单项。 每个菜单项都有一个图像和一个加速器。 退出菜单项的加速器处于活动状态。
AccelGroup agr = new AccelGroup();
AddAccelGroup(agr);
要使用加速器,我们创建一个全局AccelGroup
对象。 稍后将使用。
ImageMenuItem newi = new ImageMenuItem(Stock.New, agr);
ImageMenuItem
已创建。 图片来自图片库。
exit.AddAccelerator("activate", agr, new AccelKey(
Gdk.Key.q, Gdk.ModifierType.ControlMask, AccelFlags.Visible));
这将为退出菜单项创建 Ctrl + Q
加速器。
SeparatorMenuItem sep = new SeparatorMenuItem();
filemenu.Append(sep);
这些行创建一个分隔符。 它用于将菜单项分组为逻辑组。
图:图像 menu
CheckMenuItem
CheckMenuItem
是带有复选框的菜单项。 它可以用于布尔属性。
checkmenuitem.cs
using Gtk;
using System;
class SharpApp : Window {
private Statusbar statusbar;
public SharpApp() : base("Check menu item")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
MenuBar mb = new MenuBar();
Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;
Menu viewmenu = new Menu();
MenuItem view = new MenuItem("View");
view.Submenu = viewmenu;
CheckMenuItem stat = new CheckMenuItem("View Statusbar");
stat.Toggle();
stat.Toggled += OnStatusView;
viewmenu.Append(stat);
MenuItem exit = new MenuItem("Exit");
exit.Activated += OnActivated;
filemenu.Append(exit);
mb.Append(file);
mb.Append(view);
statusbar = new Statusbar();
statusbar.Push(1, "Ready");
VBox vbox = new VBox(false, 2);
vbox.PackStart(mb, false, false, 0);
vbox.PackStart(new Label(), true, false, 0);
vbox.PackStart(statusbar, false, false, 0);
Add(vbox);
ShowAll();
}
void OnStatusView(object sender, EventArgs args)
{
CheckMenuItem item = (CheckMenuItem) sender;
if (item.Active) {
statusbar.Show();
} else {
statusbar.Hide();
}
}
void OnActivated(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
在我们的代码示例中,我们显示一个检查菜单项。 如果该复选框已激活,则显示状态栏小部件。 如果不是,状态栏将被隐藏。
CheckMenuItem stat = new CheckMenuItem("View Statusbar");
CheckMenuItem
小部件已创建。
stat.Toggle();
Toggle()
方法选中/取消选中检查菜单项。
if (item.Active) {
statusbar.Show();
} else {
statusbar.Hide();
}
根据CheckMenuItem
的状态,我们显示或隐藏状态栏小部件。
图:CheckMenuItem
子菜单
我们的最后一个示例演示了如何在 GTK# 中创建一个子菜单。
submenu.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Submenu")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
MenuBar mb = new MenuBar();
Menu filemenu = new Menu();
MenuItem file = new MenuItem("File");
file.Submenu = filemenu;
// submenu creation
Menu imenu = new Menu();
MenuItem import = new MenuItem("Import");
import.Submenu = imenu;
MenuItem inews = new MenuItem("Import news feed...");
MenuItem ibookmarks = new MenuItem("Import bookmarks...");
MenuItem imail = new MenuItem("Import mail...");
imenu.Append(inews);
imenu.Append(ibookmarks);
imenu.Append(imail);
// exit menu item
MenuItem exit = new MenuItem("Exit");
exit.Activated += OnActivated;
filemenu.Append(import);
filemenu.Append(exit);
mb.Append(file);
VBox vbox = new VBox(false, 2);
vbox.PackStart(mb, false, false, 0);
vbox.PackStart(new Label(), false, false, 0);
Add(vbox);
ShowAll();
}
void OnActivated(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
子菜单创建。
Menu imenu = new Menu();
子菜单是Menu
。
MenuItem import = new MenuItem("Import");
import.Submenu = imenu;
它是菜单项的子菜单,它会登录到顶级文件菜单。
MenuItem inews = new MenuItem("Import news feed...");
MenuItem ibookmarks = new MenuItem("Import bookmarks...");
MenuItem imail = new MenuItem("Import mail...");
imenu.Append(inews);
imenu.Append(ibookmarks);
imenu.Append(imail);
子菜单有其自己的菜单项。
图:子菜单
在 GTK# 编程库的这一章中,我们展示了如何使用菜单。
GTK# 中的工具栏
原文: http://zetcode/gui/gtksharp/toolbars/
在 GTK# 编程教程的这一部分中,我们将使用工具栏。
菜单将我们可以在应用中使用的命令分组。 使用工具栏可以快速访问最常用的命令。 工具栏是带有按钮的水平或垂直面板。 这些按钮包含图像或图像和文本。 通过单击工具栏按钮,我们执行一个动作。
简单的工具栏
接下来,我们创建一个简单的工具栏。
toolbar.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Toolbar")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
Toolbar toolbar = new Toolbar();
toolbar.ToolbarStyle = ToolbarStyle.Icons;
ToolButton newtb = new ToolButton(Stock.New);
ToolButton opentb = new ToolButton(Stock.Open);
ToolButton savetb = new ToolButton(Stock.Save);
SeparatorToolItem sep = new SeparatorToolItem();
ToolButton quittb = new ToolButton(Stock.Quit);
toolbar.Insert(newtb, 0);
toolbar.Insert(opentb, 1);
toolbar.Insert(savetb, 2);
toolbar.Insert(sep, 3);
toolbar.Insert(quittb, 4);
quittb.Clicked += OnClicked;
VBox vbox = new VBox(false, 2);
vbox.PackStart(toolbar, false, false, 0);
Add(vbox);
ShowAll();
}
void OnClicked(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
该示例显示了一个工具栏和四个工具按钮。
Toolbar toolbar = new Toolbar();
Toolbar
小部件已创建。
toolbar.ToolbarStyle = ToolbarStyle.Icons;
在工具栏上,我们仅显示图标。 没有文字。
ToolButton newtb = new ToolButton(Stock.New);
创建带有库存图像的ToolButton
。
SeparatorToolItem sep = new SeparatorToolItem();
这是一个分隔符。 它可用于将工具栏按钮分组为逻辑组。
toolbar.Insert(newtb, 0);
toolbar.Insert(opentb, 1);
...
工具栏按钮插入到工具栏小部件中。
图:工具栏
工具栏
在第二个示例中,我们显示了两个工具栏。 许多应用具有多个工具栏。 我们展示了如何在 GTK# 中做到这一点。
toolbars.cs
using Gtk;
using System;
class SharpApp : Window {
public SharpApp() : base("Toolbars")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
Toolbar upper = new Toolbar();
upper.ToolbarStyle = ToolbarStyle.Icons;
ToolButton newtb = new ToolButton(Stock.New);
ToolButton opentb = new ToolButton(Stock.Open);
ToolButton savetb = new ToolButton(Stock.Save);
upper.Insert(newtb, 0);
upper.Insert(opentb, 1);
upper.Insert(savetb, 2);
Toolbar lower = new Toolbar();
lower.ToolbarStyle = ToolbarStyle.Icons;
ToolButton quittb = new ToolButton(Stock.Quit);
quittb.Clicked += OnClicked;
lower.Insert(quittb, 0);
VBox vbox = new VBox(false, 2);
vbox.PackStart(upper, false, false, 0);
vbox.PackStart(lower, false, false, 0);
Add(vbox);
ShowAll();
}
void OnClicked(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
我们的应用显示了两个工具栏。
Toolbar upper = new Toolbar();
...
Toolbar lower = new Toolbar();
我们创建两个Toolbar
小部件。
upper.Insert(newtb, 0);
...
lower.Insert(quittb, 0);
它们每个都有自己的工具按钮。
VBox vbox = new VBox(false, 2);
vbox.PackStart(upper, false, false, 0);
vbox.PackStart(lower, false, false, 0)
工具栏一个接一个地包装在垂直盒中。
图:工具栏 s
撤销重做
以下示例演示了如何停用工具栏上的工具栏按钮。 这是 GUI 编程中的常见做法。 例如,保存按钮。 如果我们将文档的所有更改都保存到磁盘上,则在大多数文本编辑器中,“保存”按钮将被禁用。 这样,应用会向用户指示所有更改都已保存。
undoredo.cs
using Gtk;
using System;
class SharpApp : Window {
private int count = 2;
private ToolButton undo;
private ToolButton redo;
public SharpApp() : base("Undo redo")
{
SetDefaultSize(250, 200);
SetPosition(WindowPosition.Center);
DeleteEvent += delegate { Application.Quit(); };
Toolbar toolbar = new Toolbar();
toolbar.ToolbarStyle = ToolbarStyle.Icons;
undo = new ToolButton(Stock.Undo);
redo = new ToolButton(Stock.Redo);
SeparatorToolItem sep = new SeparatorToolItem();
ToolButton quit = new ToolButton(Stock.Quit);
toolbar.Insert(undo, 0);
toolbar.Insert(redo, 1);
toolbar.Insert(sep, 2);
toolbar.Insert(quit, 3);
undo.Clicked += OnUndo;
redo.Clicked += OnRedo;
quit.Clicked += OnClicked;
VBox vbox = new VBox(false, 2);
vbox.PackStart(toolbar, false, false, 0);
vbox.PackStart(new Label(), false, false, 0);
Add(vbox);
ShowAll();
}
void OnUndo(object sender, EventArgs args)
{
count -= 1;
if (count <= 0) {
undo.Sensitive = false;
redo.Sensitive = true;
}
}
void OnRedo(object sender, EventArgs args)
{
count += 1;
if (count >= 5) {
redo.Sensitive = false;
undo.Sensitive = true;
}
}
void OnClicked(object sender, EventArgs args)
{
Application.Quit();
}
public static void Main()
{
Application.Init();
new SharpApp();
Application.Run();
}
}
我们的示例从 GTK# 库存资源创建撤消和重做按钮。 单击几下后,每个按钮均被禁用。 按钮显示为灰色。
private int count = 2;
计数变量决定哪个按钮被激活和禁用。
undo = new ToolButton(Stock.Undo);
redo = new ToolButton(Stock.Redo);
我们有两个工具按钮。 撤消和重做工具按钮。 图片来自库存资源。
undo.Clicked += OnUndo;
redo.Clicked += OnRedo;
我们为两个工具按钮都插入了Clicked
事件的方法。
if (count <= 0) {
undo.Sensitive = false;
redo.Sensitive = true;
}
要激活小部件,我们将其Sensitive
属性设置为 true。 要使其无效,我们将其设置为false
。
图:撤销和重做
在 GTK# 编程库的这一章中,我们提到了工具栏。
发布者:admin,转转请注明出处:http://www.yc00.com/web/1754948120a5219466.html
评论列表(0条)