# wxPython 图形
> 原文: [http://zetcode.com/wxpython/gdi/](http://zetcode.com/wxpython/gdi/)
GDI(图形设备接口)是用于处理图形的接口。 它用于与图形设备(例如监视器,打印机或文件)进行交互。 GDI 允许程序员在屏幕或打印机上显示数据,而不必担心特定设备的详细信息。 GDI 使程序员与硬件隔离。
从程序员的角度来看,GDI 是用于处理图形的一组类和方法。 GDI 由 2D 向量图形,字体和图像组成。
![The GDI](https://img.kancloud.cn/b0/9d/b09db60c9f39a2cb75a1bade1bbffe75_434x238.jpg)
图:GDI 结构
要开始绘制图形,我们必须创建一个设备上下文(DC)对象。 在 wxPython 中,设备上下文称为`wx.DC`。 该文档将`wx.DC`定义为可以在其上绘制图形和文本的设备上下文。 它以通用方式表示设备数量。 同一段代码可以写入不同类型的设备。 无论是屏幕还是打印机。 `wx.DC`不能直接使用。 相反,程序员应选择派生类之一。 每个派生类都打算在特定条件下使用。
## 派生的`wx.DC`类
* `wxBufferedDC`
* `wxBufferedPaintDC`
* `wxPostScriptDC`
* `wxMemoryDC`
* `wxPrinterDC`
* `wxScreenDC`
* `wxClientDC`
* `wxPaintDC`
* `wxWindowDC`
`wx.ScreenDC`用于在屏幕上的任何地方绘制。 如果要在整个窗口上绘制(仅 Windows),则使用`wx.WindowDC`。 这包括窗口装饰。 `wx.ClientDC`用于绘制窗口的客户区域。 客户区域是没有装饰(标题和边框)的窗口区域。 `wx.PaintDC`也用于绘制客户区。 但是`wx.PaintDC`和`wx.ClientDC`之间有一个区别。 仅可从`wx.PaintEvent`使用`wx.PaintDC`。 不应从`wx.PaintEvent`中使用`wx.ClientDC`。 `wx.MemoryDC`用于在位图上绘制图形。 `wx.PostScriptDC`用于在任何平台上写入 PostScript 文件。 `wx.PrinterDC`用于访问打印机(仅 Windows)。
## 画一条简单的线
我们的第一个示例将在窗口的客户区域上画一条简单的线。
```py
DrawLine(self, x1, y1, x2, y2)
```
此方法从第一个点到第二个点画一条线。 不包括第二点。
`draw_line.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws a line on the
frame window after a while.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
wx.CallLater(2000, self.DrawLine)
self.SetTitle("Line")
self.Centre()
def DrawLine(self):
dc = wx.ClientDC(self)
dc.DrawLine(50, 60, 190, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
两秒钟后,我们在框架窗口上画了一条线。
```py
wx.FutureCall(2000, self.DrawLine)
```
创建窗口后,我们将调用`DrawLine()`方法。 我们这样做是因为在创建窗口时会绘制它。 因此,我们所有的图纸都将丢失。 我们可以在创建窗口之后开始绘制。 这就是为什么我们调用`wx.FutureCall()`方法的原因。
```py
def DrawLine(self):
dc = wx.ClientDC(self)
dc.DrawLine(50, 60, 190, 60)
```
我们创建一个`wx.ClientDC`设备上下文。 唯一的参数是我们要在其上绘制的窗口。 在我们的例子中是`self`,它是对`wx.Frame`小部件的引用。 我们称为设备上下文的`DrawLine()`方法。 该调用实际上在我们的窗口上画了一条线。
了解以下行为非常重要。 如果我们调整窗口大小,该行将消失。 为什么会这样呢? 如果调整了每个窗口的大小,则会重新绘制每个窗口。 如果最大化,它也会被重画。 如果我们用另一个窗口覆盖该窗口,然后再将其打开,则该窗口也会重新绘制。 窗口被绘制为其默认状态,我们的行丢失了。 每次调整窗口大小时,我们都必须画一条线。 解决方法是`wx.PaintEvent`。 每次重新绘制窗口时都会触发此事件。 我们将在挂钩到 paint 事件的方法内绘制线条。
以下示例显示了它是如何完成的。
`draw_line2.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws a line in
a paint event.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Line")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.DrawLine(50, 60, 190, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
我们画同一条线。 这次是对绘图事件的反应。
```py
self.Bind(wx.EVT_PAINT, self.OnPaint)
```
在这里,我们将`OnPaint`方法绑定到`wx.PaintEvent`事件。 这意味着每次重新绘制窗口时,我们都会调用`OnPaint()`方法。 现在,如果我们调整窗口大小(覆盖,最大化窗口),该行将不会消失。
```py
dc = wx.PaintDC(self)
```
注意,这一次我们使用了`wx.PaintDC`设备上下文。
![Drawing a line](https://img.kancloud.cn/e2/ba/e2badd137e2a0851b800fe141de0cecb_400x250.jpg)
图:画一条线
## 计算机图形
有两种不同的计算机图形:向量和光栅图形。 栅格图形将图像表示为像素的集合。 向量图形是使用诸如点,线,曲线或多边形之类的几何图元来表示图像。 这些基元是使用数学方程式创建的。
两种类型的计算机图形都有优点和缺点。 向量图形优于栅格的优点是:
* 较小的大小
* 无限放大的能力
* 移动,缩放,填充或旋转不会降低图像质量
### 基本类型
以下是图形基元的部分列表。
* 点
* 线
* 折线
* 多边形
* 圆圈
* 椭圆
* 样条
### 设备上下文属性
设备上下文包含几个属性,例如笔刷,钢笔或字体。 `wx.Brush`是用于填充区域的绘图工具。 它用于绘制形状的背景。 它具有颜色和样式。 `wx.Pen`用于绘制形状轮廓。 它具有颜色,宽度和样式。 `wx.Font`是确定文本外观的对象。
## 基本要素
在下面的几行中,我们介绍几个基本对象:颜色,画笔,笔,连接,盖帽和渐变。
### 颜色
颜色是代表红色,绿色和蓝色(RGB)强度值的组合的对象。 有效的 RGB 值在 0 到 255 之间。有三种设置颜色的方法。 我们可以创建`wx.Colour`对象,使用预定义的颜色名称或十六进制值字符串。 `wx.Colour(0,0,255)`,`'BLUE'`和`'#0000FF'`。 这三个符号产生相同的颜色。
可以在 [colorjack.com](http://www.colorjack.com) 网站上找到处理颜色的理想工具。 或者我们可以使用 Gimp 这样的工具。
我们还提供了可在程序中使用的预定义颜色名称的列表。
| | | | | |
| --- | --- | --- | --- | --- |
| AQUAMARINE | BLACK | BLUE | BLUE VIOLET | BROWN |
| CADET BLUE | CORAL | CORNFLOWER BLUE | CYAN | DARK GREY |
| DARK GREEN | DARK OLIVE GREEN | DARK ORCHID | DARK SLATE BLUE | DARK SLATE GREY |
| DARK TURQUOISE | DIM GREY | FIREBRICK | FOREST GREEN | GOLD |
| GOLDENROD | GREY | GREEN | GREEN YELLOW | INDIAN RED |
| KHAKI | LIGHT BLUE | LIGHT GREY | LIGHT STEEL BLUE | LIME GREEN |
| MAGENTA | MAROON | MEDIUM AQUAMARINE | MEDIUM BLUE | MEDIUM FOREST GREEN |
| MEDIUM GOLDENROD | MEDIUM ORCHID | MEDIUM SEA GREEN | MEDIUM SLATE BLUE | MEDIUM SPRING GREEN |
| MEDIUM TURQUOISE | MEDIUM VIOLET RED | MIDNIGHT BLUE | NAVY | ORANGE |
| ORANGE RED | ORCHID | PALE GREEN | PINK | PLUM |
| PURPLE | RED | SALMON | SEA GREEN | SIENNA |
| SKY BLUE | SLATE BLUE | SPRING GREEN | STEEL BLUE | TAN |
| THISTLE | TURQUOISE | VIOLET | VIOLET RED | WHEAT |
| WHITE | YELLOW | YELLOW GREEN | | |
下面的示例使用一些颜色值。
`colours.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws nine coloured rectangles
on the window.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Colours")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('#d4d4d4'))
dc.SetBrush(wx.Brush('#c56c00'))
dc.DrawRectangle(10, 15, 90, 60)
dc.SetBrush(wx.Brush('#1ac500'))
dc.DrawRectangle(130, 15, 90, 60)
dc.SetBrush(wx.Brush('#539e47'))
dc.DrawRectangle(250, 15, 90, 60)
dc.SetBrush(wx.Brush('#004fc5'))
dc.DrawRectangle(10, 105, 90, 60)
dc.SetBrush(wx.Brush('#c50024'))
dc.DrawRectangle(130, 105, 90, 60)
dc.SetBrush(wx.Brush('#9e4757'))
dc.DrawRectangle(250, 105, 90, 60)
dc.SetBrush(wx.Brush('#5f3b00'))
dc.DrawRectangle(10, 195, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c'))
dc.DrawRectangle(130, 195, 90, 60)
dc.SetBrush(wx.Brush('#785f36'))
dc.DrawRectangle(250, 195, 90, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
我们绘制九个矩形,并用不同的颜色填充它们。
```py
dc.SetBrush(wx.Brush('#c56c00'))
dc.DrawRectangle(10, 15, 90, 60)
```
我们以十六进制表示法指定画笔的颜色。 笔刷是形状的背景填充。 然后,使用`DrawRectangle()`方法绘制矩形。
![Colours](https://img.kancloud.cn/12/18/121802a7fdeb463eeb970055d8706990_400x309.jpg)
图:颜色
### 笔
笔是基本的图形对象。 它用于绘制矩形,椭圆形,多边形或其他形状的线,曲线和轮廓。
```py
wx.Pen(wx.Colour colour, width=1, style=wx.SOLID)
```
`wx.Pen`构造器具有三个参数:`colour`,`width`和`style`。 以下是可能的笔样式的列表:
* `wx.solid`
* `wx.DOT`
* `wx.LONG_DASH`
* `wx.SHORT_DASH`
* `wx.DOT_DASH`
* `wx.TRANSPARENT`
`pens.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws six rectangles with different pens.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Pens")
self.Centre()
def OnPaint(self, event):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('#4c4c4c', 1, wx.SOLID))
dc.DrawRectangle(10, 15, 90, 60)
dc.SetPen(wx.Pen('#4c4c4c', 1, wx.DOT))
dc.DrawRectangle(130, 15, 90, 60)
dc.SetPen(wx.Pen('#4c4c4c', 1, wx.LONG_DASH))
dc.DrawRectangle(250, 15, 90, 60)
dc.SetPen(wx.Pen('#4c4c4c', 1, wx.SHORT_DASH))
dc.DrawRectangle(10, 105, 90, 60)
dc.SetPen(wx.Pen('#4c4c4c', 1, wx.DOT_DASH))
dc.DrawRectangle(130, 105, 90, 60)
dc.SetPen(wx.Pen('#4c4c4c', 1, wx.TRANSPARENT))
dc.DrawRectangle(250, 105, 90, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
如果未指定自定义画笔,则使用默认画笔。 默认画笔为`wx.WHITE_BRUSH`。 矩形的周长由笔绘制。 最后一个没有边界。 它是透明的,即不可见。
![Pens](https://img.kancloud.cn/14/6b/146bca1866e451a103be461fa05b43f3_400x250.jpg)
图:笔
### 连接和盖帽
笔对象具有其他两个参数:连接和盖帽。 连接定义线之间的连接如何绘制。 连接样式具有以下选项:
* `wx.JOIN_MITER`
* `wx.JOIN_BEVEL`
* `wx.JOIN_ROUND`
使用`wx.JOIN_MITER`时,线条的外边缘会延伸。 他们以一个角度相遇,并且该区域被填充。 在`wx.JOIN_BEVEL`中,两条线之间的三角形缺口被填充。 在`wx.JOIN_ROUND`中,填充了两条线之间的圆弧。 默认值为`wx.JOIN_ROUND`。
笔帽定义了笔将如何绘制线条的末端。 选项包括:
* `wx.CAP_ROUND`
* `wx.CAP_PROJECTING`
* `wx.CAP_BUTT`
`wx.CAP_ROUND`绘制圆形末端。 `wx.CAP_PROJECTING`和`wx.CAP_BUTT`画出方形末端。 它们之间的区别是`wx.CAP_PROJECTING`将超出端点超出行大小的一半。 `wx.CAP_ROUND`也将延伸到终点之外。
`joins_caps.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws uses different joins
and caps in drawing.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Joins and caps")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
pen = wx.Pen('#4c4c4c', 10, wx.SOLID)
pen.SetJoin(wx.JOIN_MITER)
dc.SetPen(pen)
dc.DrawRectangle(15, 15, 80, 50)
pen.SetJoin(wx.JOIN_BEVEL)
dc.SetPen(pen)
dc.DrawRectangle(125, 15, 80, 50)
pen.SetJoin(wx.JOIN_ROUND)
dc.SetPen(pen)
dc.DrawRectangle(235, 15, 80, 50)
pen.SetCap(wx.CAP_BUTT)
dc.SetPen(pen)
dc.DrawLine(30, 150, 150, 150)
pen.SetCap(wx.CAP_PROJECTING)
dc.SetPen(pen)
dc.DrawLine(30, 190, 150, 190)
pen.SetCap(wx.CAP_ROUND)
dc.SetPen(pen)
dc.DrawLine(30, 230, 150, 230)
pen2 = wx.Pen('#4c4c4c', 1, wx.SOLID)
dc.SetPen(pen2)
dc.DrawLine(30, 130, 30, 250)
dc.DrawLine(150, 130, 150, 250)
dc.DrawLine(155, 130, 155, 250)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
```py
pen = wx.Pen('#4c4c4c', 10, wx.SOLID)
```
为了查看各种连接样式和盖帽样式,我们需要将笔的宽度设置为大于 1。
```py
dc.DrawLine(150, 130, 150, 250)
dc.DrawLine(155, 130, 155, 250)
```
注意两条封闭的垂直线。 它们之间的距离是 5px。 恰好是当前笔宽的一半。
![Joins and Caps](https://img.kancloud.cn/1e/13/1e13c145637ffac63b9e361d67b4947a_453x304.jpg)
图:连接和盖帽
### 渐变
在计算机图形学中,渐变是从浅到深或从一种颜色到另一种颜色的阴影的平滑混合。 在 2D 绘图程序和绘图程序中,渐变用于创建彩色背景和特殊效果以及模拟灯光和阴影。
```py
GradientFillLinear(self, rect, initialColour, destColour, nDirection=RIGHT)
```
此方法使用线性渐变填充`rect`指定的区域,该区域从`initialColour`开始并最终逐渐变为`destColour`。 `nDirection`参数指定颜色改变的方向; 默认值为`wx.EAST`。
`gradients.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws four rectangles filled
with gradients.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Gradients")
self.Centre()
def OnPaint(self, event):
dc = wx.PaintDC(self)
dc.GradientFillLinear((20, 20, 180, 40), '#ffec00', '#000000', wx.NORTH)
dc.GradientFillLinear((20, 80, 180, 40), '#ffec00', '#000000', wx.SOUTH)
dc.GradientFillLinear((20, 140, 180, 40), '#ffec00', '#000000', wx.EAST)
dc.GradientFillLinear((20, 200, 180, 40), '#ffec00', '#000000', wx.WEST)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
在该示例中,四个矩形填充有渐变。
![Gradients](https://img.kancloud.cn/04/be/04bea5f7a5f7ca82ec1dadd127691fdf_250x292.jpg)
图:渐变
### `wx.brush`
画笔是基本的图形对象。 它用于绘制图形形状的背景,例如矩形,椭圆形或多边形。
wxPython 具有以下内置画笔类型:
* `wx.SOLID`
* `wx.STIPPLE`
* `wx.BDIAGONAL_HATCH`
* `wx.CROSSDIAG_HATCH`
* `wx.FDIAGONAL_HATCH`
* `wx.CROSS_HATCH`
* `wx.HORIZONTAL_HATCH`
* `wx.VERTICAL_HATCH`
* `wx.TRANSPARENT`
`brushes.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws eight rectangles filled
with different brushes.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Brushes")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetBrush(wx.Brush('#4c4c4c', wx.CROSS_HATCH))
dc.DrawRectangle(10, 15, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.SOLID))
dc.DrawRectangle(130, 15, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.BDIAGONAL_HATCH))
dc.DrawRectangle(250, 15, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.CROSSDIAG_HATCH))
dc.DrawRectangle(10, 105, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.FDIAGONAL_HATCH))
dc.DrawRectangle(130, 105, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.HORIZONTAL_HATCH))
dc.DrawRectangle(250, 105, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.VERTICAL_HATCH))
dc.DrawRectangle(10, 195, 90, 60)
dc.SetBrush(wx.Brush('#4c4c4c', wx.TRANSPARENT))
dc.DrawRectangle(130, 195, 90, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
在示例中使用了八种不同的内置画笔类型。
![Brushes](https://img.kancloud.cn/b7/5a/b75a005434de5d3064f6046f9e72ac0e_400x315.jpg)
图:笔刷
### 自定义模式
我们不限于使用预定义的模式。 我们可以轻松创建自己的自定义模式。
`custom_patterns.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws three rectangles with custom
brush patterns.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Custom patterns")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('#C7C3C3'))
brush1 = wx.Brush(wx.Bitmap('pattern1.png'))
dc.SetBrush(brush1)
dc.DrawRectangle(10, 15, 90, 60)
brush2 = wx.Brush(wx.Bitmap('pattern2.png'))
dc.SetBrush(brush2)
dc.DrawRectangle(130, 15, 90, 60)
brush3 = wx.Brush(wx.Bitmap('pattern3.png'))
dc.SetBrush(brush3)
dc.DrawRectangle(250, 15, 90, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
我们创建了一些小的位图。 位图是在 Gimp 中创建的。
```py
brush1 = wx.Brush(wx.Bitmap('pattern1.png'))
dc.SetBrush(brush1)
dc.DrawRectangle(10, 15, 90, 60)
```
从位图创建画笔,并将其设置为设备上下文。 它用于填充矩形的内部。
![Custom Patterns](https://img.kancloud.cn/14/ee/14ee98f26febc3b6260199b426042b8e_400x125.jpg)
图:自定义模式
### 点
最简单的几何对象是一个点。 它是窗口上的一个普通点。
```py
DrawPoint(self, x, y)
```
此方法在 x,y 坐标处绘制点。
`points.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws one thousand points
randomly on the window.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
import random
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Points")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('RED'))
for i in range(1000):
w, h = self.GetSize()
x = random.randint(1, w-1)
y = random.randint(1, h-1)
dc.DrawPoint(x, y)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
一个点可能很难看清,因此我们创建了 1000 个点。
```py
dc.SetPen(wx.Pen('RED'))
```
在这里,我们将笔的颜色设置为红色。
```py
w, h = self.GetSize()
x = random.randint(1, w-1)
```
这些点在窗口的客户区域周围随机分布。 它们也可以动态分配。 如果我们调整窗口的大小,将在新的客户端大小上随机绘制点。 `randint(a, b)`方法返回范围为`[a,b]`的随机整数,例如包括两点。
![Points](https://img.kancloud.cn/0d/fc/0dfcaaa23559db38b61ff9c159b7aa49_324x182.jpg)
图:绘制点
## 形状
形状是更复杂的几何对象。 在以下示例中,我们绘制了各种几何形状。
`shapes.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws various shapes on
the window.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Shapes")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetBrush(wx.Brush('#777'))
dc.SetPen(wx.Pen("#777"))
dc.DrawEllipse(20, 20, 90, 60)
dc.DrawRoundedRectangle(130, 20, 90, 60, 10)
dc.DrawArc(240, 40, 340, 40, 290, 20)
dc.DrawRectangle(20, 120, 80, 50)
dc.DrawPolygon(((130, 140), (180, 170), (180, 140), (220, 110), (140, 100)))
dc.DrawSpline(((240, 170), (280, 170), (285, 110), (325, 110)))
dc.DrawLines(((20, 260), (100, 260), (20, 210), (100, 210)))
dc.DrawCircle(170, 230, 35)
dc.DrawRectangle(250, 200, 60, 60)
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
在我们的示例中,我们绘制了一个椭圆,一个圆角矩形,一个圆弧,一个矩形,一个多边形,样条曲线,线,一个圆和一个正方形。 圆形是一种特殊的椭圆,而正方形是一种特殊的矩形。
![Shapes](https://img.kancloud.cn/9d/03/9d03bf19345482fb930f2da62a81e886_400x312.jpg)
图:形状
## 区域
设备上下文可以分为几个部分,称为区域。 区域可以是任何形状,例如矩形或圆形。 使用`Union`,`Intersect`,`Substract`和`Xor`操作,我们可以创建复杂区域。 区域用于概述,填充和裁剪。
我们可以通过三种方式创建区域。 最简单的方法是创建一个矩形区域。 可以从位图的点列表创建更复杂的区域。
在前往区域之前,我们将首先创建一个小示例。 我们将该主题分为几个部分,以便于理解。 您可能会发现修改学校数学是一个好主意。 [在这里](http://en.wikipedia.org/wiki/Circle)我们可以找到一篇不错的文章。
`lines.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program draws various shapes on
the window.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
from math import hypot, sin, cos, pi
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle('Lines')
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
size_x, size_y = self.GetClientSize()
dc.SetDeviceOrigin(size_x/2, size_y/2)
radius = hypot(size_x/2, size_y/2)
angle = 0
while (angle < 2*pi):
x = radius*cos(angle)
y = radius*sin(angle)
dc.DrawLine((0, 0), (x, y))
angle = angle + 2*pi/360
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
在此示例中,我们从客户区域的中间绘制了 360 条线。 两条线之间的距离是 1 度。 我们创造了一个有趣的人物。
```py
import wx
from math import hypot, sin, cos, pi
```
我们需要数学模块中的三个数学函数和一个常数。
```py
dc.SetDeviceOrigin(size_x/2, size_y/2)
```
方法`SetDeviceOrigin()`创建坐标系的新起点。 我们将其放入客户区的中间。 通过重新定位坐标系,我们使图形的复杂程度降低了。
```py
radius = hypot(size_x/2, size_y/2)
```
在这里,我们得到了斜边。 这是最长的线,我们可以从客户区域的中间绘制。 它是从开始到窗口角落的线段长度。 这样,大多数线条都无法完全画出。 重叠部分不可见。 参见[斜边](http://en.wikipedia.org/wiki/Hypotenuse)。
```py
x = radius*cos(angle)
y = radius*sin(angle)
```
这些是参数函数。 它们用于在曲线上找到`[x,y]`点。 从坐标系的开始一直到圆上的点绘制所有 360 条线。
![Lines](https://img.kancloud.cn/6a/8c/6a8ce879b340b8c197574919fbe7eac7_400x250.jpg)
图:直线
## 剪裁
`Clipping`将绘图限制在特定区域。 裁剪通常用于创建效果并改善应用的性能。 我们使用`SetClippingRegionAsRegion()`方法将绘图限制在特定区域。
在下面的示例中,我们将修改和增强我们以前的程序。
`star.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program demonstrates a clipping operation
when drawing a star object.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
from math import hypot, sin, cos, pi
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Star")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('#424242'))
size_x, size_y = self.GetClientSize()
dc.SetDeviceOrigin(size_x/2, size_y/2)
points = (((0, 85), (75, 75), (100, 10), (125, 75), (200, 85),
(150, 125), (160, 190), (100, 150), (40, 190), (50, 125)))
region = wx.Region(points)
dc.SetDeviceClippingRegion(region)
radius = hypot(size_x/2, size_y/2)
angle = 0
while (angle < 2*pi):
x = radius*cos(angle)
y = radius*sin(angle)
dc.DrawLine((0, 0), (x, y))
angle = angle + 2*pi/360
dc.DestroyClippingRegion()
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
我们再次绘制所有 360 线。 但是这次,只绘制了一部分客户区域。 我们将绘图限制到的区域是星形对象。
```py
region = wx.Region(points)
dc.SetDeviceClippingRegion(region)
```
我们从点列表创建一个区域。 `SetDeviceClippingRegion()`方法将图形限制在指定的区域。 在我们的情况下,它是一个恒星对象。
```py
dc.DestroyClippingRegion()
```
我们必须销毁剪切区域。
![Star](https://img.kancloud.cn/36/d7/36d7e0802354c6f7e5ee75982a7a4b16_400x250.jpg)
图:星星
## 区域操作
可以组合区域以创建更复杂的形状。 我们可以使用四个集合运算:并集,相交,减法,异或。
以下示例显示了所有正在执行的四个操作。
`region_operations.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program performs set operations on regions.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
class Example(wx.Frame):
def __init__(self, *args, **kw):
super(Example, self).__init__(*args, **kw)
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.SetTitle("Regions")
self.Centre()
def OnPaint(self, e):
dc = wx.PaintDC(self)
dc.SetPen(wx.Pen('#d4d4d4'))
dc.DrawRectangle(20, 20, 50, 50)
dc.DrawRectangle(30, 40, 50, 50)
dc.SetBrush(wx.Brush('#ffffff'))
dc.DrawRectangle(100, 20, 50, 50)
dc.DrawRectangle(110, 40, 50, 50)
region1 = wx.Region(100, 20, 50, 50)
region2 = wx.Region(110, 40, 50, 50)
region1.Intersect(region2)
rect = region1.GetBox()
dc.SetDeviceClippingRegion(region1)
dc.SetBrush(wx.Brush('#ff0000'))
dc.DrawRectangle(rect)
dc.DestroyClippingRegion()
dc.SetBrush(wx.Brush('#ffffff'))
dc.DrawRectangle(180, 20, 50, 50)
dc.DrawRectangle(190, 40, 50, 50)
region1 = wx.Region(180, 20, 50, 50)
region2 = wx.Region(190, 40, 50, 50)
region1.Union(region2)
dc.SetDeviceClippingRegion(region1)
rect = region1.GetBox()
dc.SetBrush(wx.Brush('#fa8e00'))
dc.DrawRectangle(rect)
dc.DestroyClippingRegion()
dc.SetBrush(wx.Brush('#ffffff'))
dc.DrawRectangle(20, 120, 50, 50)
dc.DrawRectangle(30, 140, 50, 50)
region1 = wx.Region(20, 120, 50, 50)
region2 = wx.Region(30, 140, 50, 50)
region1.Xor(region2)
rect = region1.GetBox()
dc.SetDeviceClippingRegion(region1)
dc.SetBrush(wx.Brush('#619e1b'))
dc.DrawRectangle(rect)
dc.DestroyClippingRegion()
dc.SetBrush(wx.Brush('#ffffff'))
dc.DrawRectangle(100, 120, 50, 50)
dc.DrawRectangle(110, 140, 50, 50)
region1 = wx.Region(100, 120, 50, 50)
region2 = wx.Region(110, 140, 50, 50)
region1.Subtract(region2)
rect = region1.GetBox()
dc.SetDeviceClippingRegion(region1)
dc.SetBrush(wx.Brush('#715b33'))
dc.DrawRectangle(rect)
dc.DestroyClippingRegion()
dc.SetBrush(wx.Brush('#ffffff'))
dc.DrawRectangle(180, 120, 50, 50)
dc.DrawRectangle(190, 140, 50, 50)
region1 = wx.Region(180, 120, 50, 50)
region2 = wx.Region(190, 140, 50, 50)
region2.Subtract(region1)
rect = region2.GetBox()
dc.SetDeviceClippingRegion(region2)
dc.SetBrush(wx.Brush('#0d0060'))
dc.DrawRectangle(rect)
dc.DestroyClippingRegion()
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
在示例中,我们提出了六个区域设置操作。
```py
region1 = wx.Region(100, 20, 50, 50)
region2 = wx.Region(110, 40, 50, 50)
region1.Intersect(region2)
```
此代码在两个区域上执行交叉操作。
![Set operations on regions](https://img.kancloud.cn/e8/19/e8198a9a34ebff9178028af358c1936e_400x250.jpg)
图:区域上的设置操作
## 映射模式
映射模式定义用于将页面空间单位转换为设备空间单位的度量单位,并且还定义设备的 x 和 y 轴的方向。
### 用英语说,用公制衡量
英语成为全球交流的语言。 度量系统也因此成为度量系统中的全局系统。 根据[维基百科文章](http://en.wikipedia.org/wiki/Metric_system)的介绍,只有三个例外。 美国,利比里亚和缅甸。 例如,美国人用华氏温度来测量温度,用加仑来加油或用磅来称重。
即使我们在欧洲使用公制,也有例外。 美国主导着 IT,我们正在导入其标准。 所以我们也说我们有一台 17 英寸的显示器。 图形可以放入文件中,可以在监视器或其他设备(相机,摄像机,移动电话)的屏幕上显示,也可以用打印机进行打印。 纸张大小可以以毫米,点或英寸为单位设置,屏幕的分辨率以像素为单位,文本的质量取决于每英寸的点数。 我们也有点,位或样本。 这是我们拥有逻辑和设备单元的原因之一。
## 逻辑和设备单元
如果在客户区上绘制文本或几何图元,则使用逻辑单元对其进行定位。
如果要绘制一些文本,请提供`text`参数和 x,y 位置。 x,y 以逻辑单位表示。 然后,设备以设备为单位绘制文本。 逻辑和设备单元可以相同,也可以不同。 逻辑单位由人(毫米)使用,设备单位是`particular`设备固有的。 例如,屏幕的本机设备单位是像素。 `HEWLETT PACKARD LaserJet 1022`的本机设备单位为 1200dpi(每英寸点数)。
到目前为止,我们已经讨论了各种度量单位。 设备的映射模式是一种将逻辑单元转换为设备单元的方法。 wxPython 具有以下映射模式:
| 映射模式 | 逻辑单元 |
| --- | --- |
| `wx.MM_TEXT` | 1 像素 |
| `wx.MM_METRIC` | 1 毫米 |
| `wx.MM_LOMETRIC` | 1/10 毫米 |
| `wx.MM_POINTS` | 1 点,1/72 英寸 |
| `wx.MM_TWIPS` | 点的 1/20 或 1/1440 英寸 |
默认的映射模式是`wx.MM_TEXT`。 在此模式下,逻辑单元与设备单元相同。 人们将对象放置在屏幕上或设计网页时,他们通常以像素为单位思考。 Web 设计人员创建三列页面,这些列以像素为单位设置。 页面的最低公分母通常是 800px 等。这种想法很自然,因为我们知道我们的显示器具有`1024x768`像素,我们不打算进行转换,而是习惯于以像素为单位进行思考。 如果要以毫米为单位绘制结构,则可以使用两种度量映射模式。 对于屏幕而言,以毫米为单位直接绘制太厚了,这就是为什么我们要使用`wx.MM_LOMETRIC`映射模式。
要设置不同的映射模式,我们使用`SetMapMode()`方法。
## 标尺示例
标尺以像素为单位测量屏幕对象。
`ruler.py`
```py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
ZetCode wxPython tutorial
This program creates a ruler.
author: Jan Bodnar
website: zetcode.com
last edited: May 2018
"""
import wx
RW = 701 # ruler width
RM = 10 # ruler margin
RH = 80 # ruler height
class Example(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, size=(RW + 2*RM, RH),
style=wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.STAY_ON_TOP)
self.font = wx.Font(7, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL,
wx.FONTWEIGHT_BOLD, False, 'Courier 10 Pitch')
self.InitUI()
def InitUI(self):
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Centre()
self.Show(True)
def OnPaint(self, e):
dc = wx.PaintDC(self)
brush = wx.Brush(wx.Bitmap('granite.png'))
dc.SetBrush(brush)
dc.DrawRectangle(0, 0, RW+2*RM, RH)
dc.SetFont(self.font)
dc.SetPen(wx.Pen('#F8FF25'))
dc.SetTextForeground('#F8FF25')
for i in range(RW):
if not (i % 100):
dc.DrawLine(i+RM, 0, i+RM, 10)
w, h = dc.GetTextExtent(str(i))
dc.DrawText(str(i), i+RM-w/2, 11)
elif not (i % 20):
dc.DrawLine(i+RM, 0, i+RM, 8)
elif not (i % 2):
dc.DrawLine(i+RM, 0, i+RM, 4)
def OnLeftDown(self, e):
x, y = self.ClientToScreen(e.GetPosition())
ox, oy = self.GetPosition()
dx = x - ox
dy = y - oy
self.delta = ((dx, dy))
def OnMouseMove(self, e):
if e.Dragging() and e.LeftIsDown():
self.SetCursor(wx.Cursor(wx.CURSOR_HAND))
x, y = self.ClientToScreen(e.GetPosition())
fp = (x - self.delta[0], y - self.delta[1])
self.Move(fp)
def OnLeftUp(self, e):
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
def OnRightDown(self, e):
self.Close()
def main():
app = wx.App()
ex = Example(None)
ex.Show()
app.MainLoop()
if __name__ == '__main__':
main()
```
在此示例中,我们创建一个标尺。 此标尺以像素为单位测量屏幕对象。 我们保留了默认的映射模式,即`wx.MM_TEXT`。 正如我们已经提到的,此模式具有相同的逻辑和设备单元。 在我们的例子中,这些是像素。
```py
def __init__(self, parent):
wx.Frame.__init__(self, parent, size=(RW + 2*RM, RH),
style=wx.FRAME_NO_TASKBAR | wx.NO_BORDER | wx.STAY_ON_TOP)
```
我们创建了一个无边界的窗口。 标尺宽 721 像素:`RW + 2 * RM = 701 + 20 = 721`。标尺显示 700 个数字;`0 ... 700`为 701 像素。 标尺两边都有空白,`2 * 10`是 20 像素。 两者合计为 721 像素。
```py
brush = wx.Brush(wx.Bitmap('granite.png'))
dc.SetBrush(brush)
dc.DrawRectangle(0, 0, RW+2*RM, RH)
```
在这里,我们在窗口上绘制一个自定义模式。 我们使用了 Gimp 中可用的预定义模式。 它被称为花岗岩。
```py
w, h = dc.GetTextExtent(str(i))
dc.DrawText(str(i), i+RM-w/2, 11)
```
这些行确保我们正确对齐文本。 `GetTextExtent()`方法返回文本的宽度和高度。
窗口周围没有边框。 因此,我们必须手动处理移动。 `OnLeftDown()`和`OnMouseMove()`方法使我们能够移动标尺。
```py
def OnLeftDown(self, e):
x, y = self.ClientToScreen(e.GetPosition())
ox, oy = self.GetPosition()
dx = x - ox
dy = y - oy
self.delta = ((dx, dy))
```
在`OnLeftDown()`方法中,我们确定窗口和鼠标光标的坐标;`delta`值是鼠标指针距窗口左上角的距离。 我们需要`delta`值才能移动窗口。
```py
def OnMouseMove(self, e):
if e.Dragging() and e.LeftIsDown():
self.SetCursor(wx.Cursor(wx.CURSOR_HAND))
x, y = self.ClientToScreen(e.GetPosition())
fp = (x - self.delta[0], y - self.delta[1])
self.Move(fp)
```
当我们同时拖动窗口并按下鼠标左键时,将执行该代码。 在代码块中,我们使用`SetCursor()`更改鼠标光标,并使用`Move()`方法移动窗口。 增量值用于获取距离。
```py
def OnLeftUp(self, e):
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
```
释放鼠标左键时,将光标改回到箭头。
```py
def OnRightDown(self, e):
self.Close()
```
右键单击窗口区域可关闭窗口。
![Ruler example](https://img.kancloud.cn/a9/eb/a9eb5556012cb30e8eb2901ff9e27955_719x55.jpg)
图:标尺示例
在本章中,我们使用了 wxPython 中的图形。
- ZetCode 数据库教程
- MySQL 教程
- MySQL 简介
- MySQL 安装
- MySQL 的第一步
- MySQL 快速教程
- MySQL 存储引擎
- MySQL 数据类型
- 在 MySQL 中创建,更改和删除表
- MySQL 表达式
- 在 MySQL 中插入,更新和删除数据
- MySQL 中的SELECT语句
- MySQL 子查询
- MySQL 约束
- 在 MySQL 中导出和导入数据
- 在 MySQL 中连接表
- MySQL 函数
- MySQL 中的视图
- MySQL 中的事务
- MySQL 存储过程
- MySQL Python 教程
- MySQL Perl 教程
- MySQL & Perl DBI
- 使用 Perl 连接到 MySQL 数据库
- MySQL 中的 Perl 错误处理
- 使用 Perl 进行 MySQL 查询
- 在 MySQL 中使用 Perl 绑定参数&列
- 在 MySQL 中使用 Perl 处理图像
- 使用 Perl 获取 MySQL 元数据
- Perl 的 MySQL 事务
- MySQL C API 编程教程
- MySQL Visual Basic 教程
- MySQL PHP 教程
- MySQL Java 教程
- MySQL Ruby 教程
- MySQL C# 教程
- SQLite 教程
- SQLite 简介
- sqlite3 命令行工具
- 在 SQLite 中创建,删除和更改表
- SQLite 表达式
- SQLite 插入,更新,删除数据
- SQLite SELECT语句
- SQLite 约束
- SQLite 连接表
- SQLite 函数
- SQLite 视图,触发器,事务
- SQLite C 教程
- SQLite Python 教程
- SQLite Perl 教程
- Perl DBI
- 使用 Perl 连接到 SQLite 数据库
- SQLite Perl 错误处理
- 使用 Perl 的 SQLite 查询
- 使用 Perl 绑定 SQLite 参数&列
- 使用 Perl 在 SQLite 中处理图像
- 使用 Perl 获取 SQLite 元数据
- 使用 Perl 进行 SQLite 事务
- SQLite Ruby 教程
- 连接到 SQLite 数据库
- 在 SQLite 中使用 Ruby 进行 SQL 查询
- 绑定参数
- 处理图像
- 使用 Ruby 获取 SQLite 元数据
- Ruby 的 SQLite 事务
- SQLite C# 教程
- SQLite C# 简介
- 使用SqliteDataReader检索数据
- ADO.NET 数据集
- 使用 C# 在 SQLite 中处理图像
- 使用 C# 获取 SQLite 元数据
- 使用 C# 的 SQLite 事务
- SQLite Visual Basic 教程
- SQLite Visual Basic 简介
- 使用SqliteDataReader检索数据
- ADO.NET 的数据集
- 使用 Visual Basic 在 SQLite 中处理图像
- 使用 Visual Basic 获取 SQLite 元数据
- 使用 Visual Basic 的 SQLite 事务
- PostgreSQL C 教程
- PostgreSQL Ruby 教程
- PostgreSQL PHP 教程
- PostgreSQL PHP 编程简介
- 在 PostgreSQL 中使用 PHP 检索数据
- 在 PostgreSQL 中使用 PHP 处理图像
- 用 PHP 获取 PostgreSQL 元数据
- 在 PostgreSQL 中使用 PHP 进行事务
- PostgreSQL Java 教程
- Apache Derby 教程
- Derby 简介
- Derby 的安装&配置
- Derby 工具
- ij 工具
- Derby 中的 SQL 查询
- 在 Derby 中使用 JDBC 进行编程
- Derby 安全
- 使用 Derby & Apache Tomcat
- NetBeans 和 Derby
- SQLAlchemy 教程
- SQLAlchemy 简介
- 原始 SQL
- 模式定义语言
- SQL 表达式语言
- SQLAlchemy 中的对象关系映射器
- MongoDB PHP 教程
- MongoDB JavaScript 教程
- MongoDB Ruby 教程
- Spring JdbcTemplate 教程
- JDBI 教程
- MyBatis 教程
- Hibernate Derby 教程
- ZetCode .NET 教程
- Visual Basic 教程
- Visual Basic
- Visual Basic 语法结构
- 基本概念
- Visual Basic 数据类型
- Visual Basic 中的字符串
- 运算符
- 控制流
- Visual Basic 数组
- Visual Basic 中的过程&函数
- 在 Visual Basic 中组织代码
- 面向对象编程
- Visual Basic 中的面向对象编程 II
- Visual Basic 中的集合
- 输入和输出
- C# 教程
- C# 语言
- C# 语法结构
- C# 基础
- C# 数据类型
- C# 中的字符串
- C# 运算符
- C# 中的流控制
- C# 数组
- C# 面向对象编程
- C# 中的方法
- C# 面向对象编程 II
- C# 属性
- C# 结构
- C# 委托
- 命名空间
- C# 集合
- C# 输入和输出
- C# 目录教程
- C# 字典教程
- 在 C# 中读取文本文件
- C# 中的日期和时间
- 在 C# 中读取网页
- C# HttpClient教程
- ASP.NET Core 教程
- ZetCode 图形教程
- Java 2D 游戏教程
- Java 游戏基础
- 动画
- 移动精灵
- 碰撞检测
- Java 益智游戏
- Java Snake
- Breakout 游戏
- Java 俄罗斯方块
- Java 吃豆人
- Java 太空侵略者
- Java 扫雷
- Java 推箱子
- Java 2D 教程
- 介绍
- 基本绘图
- 形状和填充
- 透明度
- 合成
- 剪裁
- 变换
- 特效
- 图像
- 文字和字体
- 命中测试,移动物体
- 俄罗斯方块
- Cario 图形教程
- Cario 图形库
- Cario 定义
- Cairo 后端
- Cairo 基本图形
- 形状和填充
- 渐变
- 透明度
- 合成
- 剪裁和遮罩
- 变换
- Cairo 文字
- Cairo 中的图像
- 根窗口
- PyCairo 教程
- PyCairo 简介
- PyCairo 后端
- PyCairo 中的基本绘图
- PyCairo 形状和填充
- PyCairo 渐变
- PyCairo 剪裁&遮罩
- PyCairo 的透明度
- PyCairo 中的变换
- PyCairo 中的文字
- PyCairo 中的图像
- 根窗口
- HTML5 画布教程
- 介绍
- HTML5 画布中的直线
- HTML5 画布形状
- HTML5 画布填充
- HTML5 画布中的透明度
- HTML5 画布合成
- HTML5 canvas 中的变换
- HTML5 画布中的文字
- HTML5 画布中的动画
- HTML5 画布中的 Snake
- ZetCode GUI 教程
- Windows API 教程
- Windows API 简介
- Windows API main函数
- Windows API 中的系统函数
- Windows API 中的字符串
- Windows API 中的日期和时间
- Windows API 中的一个窗口
- UI 的第一步
- Windows API 菜单
- Windows API 对话框
- Windows API 控件 I
- Windows API 控件 II
- Windows API 控件 III
- Windows API 中的高级控件
- Windows API 中的自定义控件
- Windows API 中的 GDI
- PyQt4 教程
- PyQt4 简介
- PyQt4 中的第一个程序
- PyQt4 中的菜单和工具栏
- PyQt4 中的布局管理
- PyQt4 中的事件和信号
- PyQt4 中的对话框
- PyQt4 小部件
- PyQt4 小部件 II
- PyQt4 中的拖放
- PyQt4 中的绘图
- PyQt4 中的自定义小部件
- PyQt4 中的俄罗斯方块游戏
- PyQt5 教程
- PyQt5 简介
- PyQt5 日期和时间
- PyQt5 中的第一个程序
- PyQt5 中的菜单和工具栏
- PyQt5 中的布局管理
- PyQt5 中的事件和信号
- PyQt5 中的对话框
- PyQt5 小部件
- PyQt5 小部件 II
- PyQt5 拖放
- PyQt5 中的绘图
- PyQt5 中的自定义小部件
- PyQt5 中的俄罗斯方块
- Qt4 教程
- Qt4 工具包简介
- Qt4 工具类
- Qt4 中的字符串
- Qt4 中的日期和时间
- 在 Qt4 中使用文件和目录
- Qt4 中的第一个程序
- Qt4 中的菜单和工具栏
- Qt4 中的布局管理
- Qt4 中的事件和信号
- Qt4 小部件
- Qt4 小部件 II
- Qt4 中的绘图
- Qt4 中的自定义小部件
- Qt4 中的打砖块游戏
- Qt5 教程
- Qt5 工具包简介
- Qt5 中的字符串
- Qt5 中的日期和时间
- Qt5 中的容器
- 在 Qt5 中处理文件和目录
- Qt5 中的第一个程序
- Qt5 中的菜单和工具栏
- Qt5 中的布局管理
- Qt5 中的事件和信号
- Qt5 小部件
- Qt5 小部件 II
- Qt5 中的绘图
- Qt5 中的自定义小部件
- Qt5 中的贪食蛇
- Qt5 中的打砖块游戏
- PySide 教程
- PySide 工具包简介
- PySide 中的第一个程序
- PySide 中的菜单和工具栏
- PySide 中的布局管理
- PySide 中的事件和信号
- PySide 中的对话框
- PySide 小部件
- PySide 小部件 II
- 在 PySide 中拖放
- 在 PySide 中绘图
- PySide 中的自定义小部件
- PySide 中的俄罗斯方块游戏
- Tkinter 教程
- Tkinter 简介
- Tkinter 中的布局管理
- Tkinter 标准小部件属性
- Tkinter 小部件
- Tkinter 中的菜单和工具栏
- Tkinter 中的对话框
- Tkinter 中的绘图
- Tkinter 中的贪食蛇
- Tcl/Tk 教程
- Tcl/Tk 简介
- Tcl/Tk 中的布局管理
- Tcl/Tk 小部件
- Tcl/Tk 中的菜单和工具栏
- Tcl/Tk 中的对话框
- Tcl/Tk 绘图
- 贪食蛇
- Qt 快速教程
- Java Swing 教程
- Java Swing 简介
- Java Swing 首个程序
- Java Swing 中的菜单和工具栏
- Swing 布局管理
- GroupLayout管理器
- Java Swing 事件
- 基本的 Swing 组件
- 基本的 Swing 组件 II
- Java Swing 对话框
- Java Swing 模型架构
- Swing 中的拖放
- Swing 中的绘图
- Java Swing 中的可调整大小的组件
- Java Swing 中的益智游戏
- 俄罗斯方块
- JavaFX 教程
- JavaFX 简介
- JavaFX 首个程序
- JavaFX 布局窗格
- 基本的 JavaFX 控件
- 基本 JavaFX 控件 II
- JavaFX 事件
- JavaFX 效果
- JavaFX 动画
- JavaFX 画布
- JavaFX 图表
- Java SWT 教程
- Java SWT 简介
- Java SWT 中的布局管理
- Java SWT 中的菜单和工具栏
- Java SWT 中的小部件
- Table小部件
- Java SWT 中的对话框
- Java SWT 绘图
- Java SWT 中的贪食蛇
- wxWidgets 教程
- wxWidgets 简介
- wxWidgets 助手类
- wxWidgets 中的第一个程序
- wxWidgets 中的菜单和工具栏
- wxWidgets 中的布局管理
- wxWidgets 中的事件
- wxWidgets 中的对话框
- wxWidgets 小部件
- wxWidgets 小部件 II
- wxWidgets 中的拖放
- wxWidgets 中的设备上下文
- wxWidgets 中的自定义小部件
- wxWidgets 中的俄罗斯方块游戏
- wxPython 教程
- wxPython 简介
- 第一步
- 菜单和工具栏
- wxPython 中的布局管理
- wxPython 中的事件
- wxPython 对话框
- 小部件
- wxPython 中的高级小部件
- wxPython 中的拖放
- wxPython 图形
- 创建自定义小部件
- wxPython 中的应用框架
- wxPython 中的俄罗斯方块游戏
- C# Winforms Mono 教程
- Mono Winforms 简介
- Mono Winforms 中的第一步
- Mono Winforms 中的布局管理
- Mono Winforms 中的菜单和工具栏
- Mono Winforms 中的基本控件
- Mono Winforms 中的高级控件
- 对话框
- Mono Winforms 中的拖放
- Mono Winforms 中的绘图
- Mono Winforms 中的贪食蛇
- Java Gnome 教程
- Java Gnome 简介
- Java Gnome 的第一步
- Java Gnome 中的布局管理
- Java Gnome 中的布局管理 II
- Java Gnome 中的菜单
- Java Gnome 中的工具栏
- Java Gnome 中的事件
- Java Gnome 中的小部件
- Java Gnome 中的小部件 II
- Java Gnome 中的高级小部件
- Java Gnome 中的对话框
- Java Gnome 中的 Pango
- 在 Java Gnome 中用 Cairo 绘图
- Cario 绘图 II
- Java Gnome 中的贪食蛇
- QtJambi 教程
- QtJambi 简介
- QtJambi 中的布局管理
- QtJambi 中的小部件
- QtJambi 中的菜单和工具栏
- QtJambi 对话框
- QtJambi 中的绘图
- QtJambi 中的自定义小部件
- 贪食蛇
- GTK+ 教程
- GTK+ 简介
- GTK+ 中的第一个程序
- GTK+ 中的菜单和工具栏
- GTK+ 布局管理
- GTK+ 事件和信号
- GTK+ 对话框
- GTK+ 小部件
- GTK+ 小部件 II
- GtkTreeView小部件
- GtkTextView小部件
- 自定义 GTK+ 小部件
- Ruby GTK 教程
- Ruby GTK 简介
- Ruby GTK 中的布局管理
- Ruby GTK 中的小部件
- Ruby GTK 中的菜单和工具栏
- Ruby GTK 中的对话框
- Ruby GTK Cario 绘图
- Ruby GTK 中的自定义小部件
- Ruby GTK 中的贪食蛇
- GTK# 教程
- GTK# 简介
- GTK 的第一步
- GTK# 中的布局管理
- GTK 中的菜单
- GTK# 中的工具栏
- GTK# 中的事件
- GTK# 中的小部件
- GTK 中的小部件 II
- GTK# 中的高级小部件
- GTK# 中的对话框
- Pango
- GTK# 中的 Cario 绘图
- GTK# 中的 Cario 绘图 II
- GTK# 中的自定义小部件
- Visual Basic GTK# 教程
- Visual Basic GTK# 简介
- 布局管理
- 小部件
- 菜单和工具栏
- 对话框
- Cario 绘图
- 自定义小部件
- 贪食蛇
- PyGTK 教程
- PyGTK 简介
- PyGTK 的第一步
- PyGTK 中的布局管理
- PyGTK 中的菜单
- PyGTK 中的工具栏
- PyGTK 中的事件和信号
- PyGTK 中的小部件
- PyGTK 中的小部件 II
- PyGTK 中的高级小部件
- PyGTK 中的对话框
- Pango
- Pango II
- PyGTK 中的 Cario 绘图
- Cario 绘图 II
- PyGTK 中的贪食蛇游戏
- PyGTK 中的自定义小部件
- PHP GTK 教程
- PHP GTK 简介
- PHP GTK 中的布局管理
- PHP GTK 中的小部件
- PHP GTK 中的菜单和工具栏
- 对话框
- Cario 绘图
- 自定义小部件
- 贪食蛇
- C# Qyoto 教程
- Qyoto 介绍
- 布局管理
- Qyoto 中的小部件
- Qyoto 中的菜单和工具栏
- Qyoto 对话框
- Qyoto 中的绘图
- Qyoto 中的绘图 II
- Qyoto 中的自定义小部件
- 贪食蛇
- Ruby Qt 教程
- Ruby Qt 简介
- Ruby Qt 中的布局管理
- Ruby Qt 中的小部件
- 菜单和工具栏
- Ruby Qt 中的对话框
- 用 Ruby Qt 绘图
- Ruby Qt 中的自定义小部件
- Ruby Qt 中的贪食蛇
- Visual Basic Qyoto 教程
- Qyoto 介绍
- 布局管理
- Qyoto 中的小部件
- Qyoto 中的菜单和工具栏
- Qyoto 对话框
- Qyoto 中的绘图
- Qyoto 中的自定义小部件
- 贪食蛇
- Mono IronPython Winforms 教程
- 介绍
- IronPython Mono Winforms 中的第一步
- 布局管理
- 菜单和工具栏
- Mono Winforms 中的基本控件
- Mono Winforms 中的基本控件 II
- Mono Winforms 中的高级控件
- 对话框
- Mono Winforms 中的拖放
- 绘图
- IronPython Mono Winforms 中的绘图 II
- IronPython Mono Winforms 中的贪食蛇
- IronPython Mono Winforms 中的俄罗斯方块游戏
- FreeBASIC GTK 教程
- Jython Swing 教程
- Jython Swing 简介
- Jython Swing 中的布局管理
- Jython Swing 中的组件
- Jython Swing 中的菜单和工具栏
- Jython Swing 中的对话框
- Jython Swing 中的绘图
- Jython Swing 中的半字节
- JRuby Swing 教程
- JRuby Swing 简介
- JRuby Swing 中的布局管理
- JRuby Swing 中的组件
- 菜单和工具栏
- JRuby Swing 中的对话框
- 在 JRuby Swing 中绘图
- JRuby Swing 中的贪食蛇
- Visual Basic Winforms 教程
- Visual Basic Winforms 简介
- 布局管理
- 基本控制
- 进阶控件
- 菜单和工具栏
- 对话框
- 绘图
- 拖放
- 贪食蛇
- JavaScript GTK 教程
- JavaScript GTK 简介
- 布局管理
- JavaScript GTK 中的小部件
- JavaScript GTK 中的菜单和工具栏
- JavaScript GTK 中的对话框
- JavaScript GTK 中的 Cario 绘图
- ZetCode Java 教程
- Java 教程
- Java 语言
- Java 语法结构
- Java 基础
- Java 数据类型
- Java 数据类型 II
- Java 字符串
- Java 数组
- Java 表达式
- Java 控制流程
- Java 面向对象的编程
- Java 方法
- Java 面向对象编程 II
- Java 包
- Java 中的异常
- Java 集合
- Java 流
- Java Future 教程
- Java Comparable和Comparator
- Java DOM 教程
- Java MVC 教程
- Java SAX 教程
- Java JAXB 教程
- Java JSON 处理教程
- Java H2 教程
- MongoDB Java 教程
- Java 正则表达式教程
- Java PDFBox 教程
- Java 文件教程
- Java Files.list教程
- Java Files.walk教程
- Java DirectoryStream教程
- Java 外部与内部迭代器
- Java 文件大小
- 用 Java 创建目录
- 用 Java 创建文件
- Java Log4j 教程
- Gson 教程
- Java RequestDispatcher
- Java HTTP GET/POST 请求
- Java InputStream教程
- Java FileOutputStream教程
- Java FileInputStream教程
- Java ZipInputStream教程
- Java FileWriter教程
- EJB 简介
- Java forEach教程
- Jetty 教程
- Tomcat Derby 教程
- Stripes 介绍
- 使用 Stripes 的 Java webapp,MyBatis,& Derby
- EclipseLink 简介
- Java 中的数据源
- JSTL 中的 SQL 查询标记
- Java 验证过滤器
- Hibernate 验证器
- 用 Java 显示图像
- Play 框架简介
- Spark Java 简介
- Java ResourceBundle教程
- Jtwig 教程
- Java Servlet 教程
- Java 套接字教程
- FreeMarker 教程
- Android 教程
- Java EE 5 教程
- JSoup 教程
- JFreeChart 教程
- ImageIcon教程
- 用 Java 复制文件
- Java 文件时间教程
- 如何使用 Java 获取当前日期时间
- Java 列出目录内容
- Java 附加到文件
- Java ArrayList教程
- 用 Java 读写 ICO 图像
- Java int到String的转换
- Java HashSet教程
- Java HashMap教程
- Java static关键字
- Java 中的HashMap迭代
- 用 Java 过滤列表
- 在 Java 中读取网页
- Java 控制台应用
- Java 集合的便利工厂方法
- Google Guava 简介
- OpenCSV 教程
- 用 Java8 的StringJoiner连接字符串
- Java 中元素迭代的历史
- Java 谓词
- Java StringBuilder
- Java 分割字串教学
- Java NumberFormat
- Java TemporalAdjusters教程
- Apache FileUtils教程
- Java Stream 过滤器
- Java 流归约
- Java 流映射
- Java InputStreamReader教程
- 在 Java 中读取文本文件
- Java Unix 时间
- Java LocalTime
- Java 斐波那契
- Java ProcessBuilder教程
- Java 11 的新功能
- ZetCode JavaScript 教程
- Ramda 教程
- Lodash 教程
- Collect.js 教程
- Node.js 简介
- Node HTTP 教程
- Node-config 教程
- Dotenv 教程
- Joi 教程
- Liquid.js 教程
- faker.js 教程
- Handsontable 教程
- PouchDB 教程
- Cheerio 教程
- Axios 教程
- Jest 教程
- JavaScript 正则表达式
- 用 JavaScript 创建对象
- Big.js 教程
- Moment.js 教程
- Day.js 教程
- JavaScript Mustache 教程
- Knex.js 教程
- MongoDB JavaScript 教程
- Sequelize 教程
- Bookshelf.js 教程
- Node Postgres 教程
- Node Sass 教程
- Document.querySelector教程
- Document.all教程
- JSON 服务器教程
- JavaScript 贪食蛇教程
- JavaScript 构建器模式教程
- JavaScript 数组
- XMLHttpRequest教程
- 从 JavaScript 中的 URL 读取 JSON
- 在 JavaScript 中循环遍历 JSON 数组
- jQuery 教程
- Google 图表教程
- ZetCode Kotlin 教程
- Kotlin Hello World 教程
- Kotlin 变量
- Kotlin 的运算符
- Kotlin when表达式
- Kotlin 数组
- Kotlin 范围
- Kotlin Snake
- Kotlin Swing 教程
- Kotlin 字符串
- Kotlin 列表
- Kotlin 映射
- Kotlin 集合
- Kotlin 控制流程
- Kotlin 写入文件
- Kotlin 读取文件教程
- Kotlin 正则表达式
- ZetCode 其它教程
- TCL 教程
- Tcl
- Tcl 语法结构
- Tcl 中的基本命令
- Tcl 中的表达式
- Tcl 中的控制流
- Tcl 中的字符串
- Tcl 列表
- Tcl 中的数组
- Tcl 中的过程
- 输入&输出
- AWK 教程
- Vaadin 教程
- Vaadin 框架介绍
- Vaadin Grid教程
- Vaadin TextArea教程
- Vaadin ComboBox教程
- Vaadin Slider教程
- Vaadin CheckBox教程
- Vaadin Button教程
- Vaadin DateField教程
- Vaadin Link教程
- ZetCode PHP 教程
- PHP 教程
- PHP
- PHP 语法结构
- PHP 基础
- PHP 数据类型
- PHP 字符串
- PHP 运算符
- PHP 中的控制流
- PHP 数组
- PHP 数组函数
- PHP 中的函数
- PHP 正则表达式
- PHP 中的面向对象编程
- PHP 中的面向对象编程 II
- PHP Carbon 教程
- PHP Monolog 教程
- PHP 配置教程
- PHP Faker 教程
- Twig 教程
- Valitron 教程
- Doctrine DBAL QueryBuilder 教程
- PHP Respect 验证教程
- PHP Rakit 验证教程
- PHP PDO 教程
- CakePHP 数据库教程
- PHP SQLite3 教程
- PHP 文件系统函数
- ZetCode Python 教程
- Python 教程
- Python 语言
- 交互式 Python
- Python 语法结构
- Python 数据类型
- Python 字符串
- Python 列表
- Python 字典
- Python 运算符
- Python 关键字
- Python 函数
- Python 中的文件
- Python 中的面向对象编程
- Python 模块
- Python 中的包
- Python 异常
- Python 迭代器和生成器
- Python 内省
- Python Faker 教程
- Python f 字符串教程
- Python bcrypt 教程
- Python 套接字教程
- Python smtplib教程
- OpenPyXL 教程
- Python pathlib教程
- Python YAML 教程
- Python 哈希教程
- Python ConfigParser教程
- Python 日志教程
- Python argparse 教程
- Python SQLite 教程
- Python Cerberus 教程
- Python PostgreSQL 教程
- PyMongo 教程
- PyMySQL 教程
- Peewee 教程
- pyDAL 教程
- pytest 教程
- Bottle 教程
- Python Jinja 教程
- PrettyTable 教程
- BeautifulSoup 教程
- pyquery 教程
- Python for循环
- Python 反转
- Python Lambda 函数
- Python 集合
- Python 映射
- Python CSV 教程-读写 CSV
- Python 正则表达式
- Python SimpleJson 教程
- SymPy 教程
- Pandas 教程
- Matplotlib 教程
- Pillow 教程
- Python FTP 教程
- Python Requests 教程
- Python Arrow 教程
- Python 列表推导式
- Python 魔术方法
- PyQt 中的QPropertyAnimation
- PyQt 中的QNetworkAccessManager
- ZetCode Ruby 教程
- Ruby 教程
- Ruby
- Ruby 语法结构
- Ruby 基础
- Ruby 变量
- Ruby 中的对象
- Ruby 数据类型
- Ruby 字符串
- Ruby 表达式
- Ruby 控制流
- Ruby 数组
- Ruby 哈希
- Ruby 中的面向对象编程
- Ruby 中的面向对象编程 II
- Ruby 正则表达式
- Ruby 输入&输出
- Ruby HTTPClient教程
- Ruby Faraday 教程
- Ruby Net::HTTP教程
- ZetCode Servlet 教程
- 从 Java Servlet 提供纯文本
- Java Servlet JSON 教程
- Java Servlet HTTP 标头
- Java Servlet 复选框教程
- Java servlet 发送图像教程
- Java Servlet JQuery 列表教程
- Servlet FreeMarker JdbcTemplate 教程-CRUD 操作
- jQuery 自动补全教程
- Java servlet PDF 教程
- servlet 从 WAR 内读取 CSV 文件
- Java HttpServletMapping
- EasyUI datagrid
- Java Servlet RESTFul 客户端
- Java Servlet Log4j 教程
- Java Servlet 图表教程
- Java ServletConfig教程
- Java Servlet 读取网页
- 嵌入式 Tomcat
- Java Servlet 分页
- Java Servlet Weld 教程
- Java Servlet 上传文件
- Java Servlet 提供 XML
- Java Servlet 教程
- JSTL forEach标签
- 使用 jsGrid 组件
- ZetCode Spring 教程
- Spring @Bean注解教程
- Spring @Autowired教程
- Spring @GetMapping教程
- Spring @PostMapping教程
- Spring @DeleteMapping教程
- Spring @RequestMapping教程
- Spring @PathVariable教程
- Spring @RequestBody教程
- Spring @RequestHeader教程
- Spring Cookies 教程
- Spring 资源教程
- Spring 重定向教程
- Spring 转发教程
- Spring ModelAndView教程
- Spring MessageSource教程
- Spring AnnotationConfigApplicationContext
- Spring BeanFactoryPostProcessor教程
- Spring BeanFactory教程
- Spring context:property-placeholder教程
- Spring @PropertySource注解教程
- Spring @ComponentScan教程
- Spring @Configuration教程
- Spring C 命名空间教程
- Spring P 命名空间教程
- Spring bean 引用教程
- Spring @Qualifier注解教程
- Spring ClassPathResource教程
- Spring 原型作用域 bean
- Spring Inject List XML 教程
- Spring 概要文件 XML 教程
- Spring BeanDefinitionBuilder教程
- Spring 单例作用域 bean
- 独立的 Spring 应用
- 经典 Spring 应用中的JdbcTemplate
- Spring EmbeddedDatabaseBuilder教程
- Spring HikariCP 教程
- Spring Web 应用简介
- Spring BeanPropertyRowMapper教程
- Spring DefaultServlet教程
- Spring WebSocket 教程
- Spring WebJars 教程
- Spring @MatrixVariable教程
- Spring Jetty 教程
- Spring 自定义 404 错误页面教程
- Spring WebApplicationInitializer教程
- Spring BindingResult教程
- Spring FreeMarker 教程
- Spring Thymeleaf 教程
- Spring ResourceHandlerRegistry教程
- SpringRunner 教程
- Spring MockMvc 教程
- ZetCode Spring Boot 教程
- Spring Boot 发送电子邮件教程
- Spring Boot WebFlux 教程
- Spring Boot ViewControllerRegistry教程
- Spring Boot CommandLineRunner教程
- Spring Boot ApplicationReadyEvent 教程
- Spring Boot CORS 教程
- Spring Boot @Order教程
- Spring Boot @Lazy教程
- Spring Boot Flash 属性
- Spring Boot CrudRepository 教程
- Spring Boot JpaRepository 教程
- Spring Boot findById 教程
- Spring Boot Data JPA @NamedQuery教程
- Spring Boot Data JPA @Query教程
- Spring Boot Querydsl 教程
- Spring Boot Data JPA 排序教程
- Spring Boot @DataJpaTest教程
- Spring Boot TestEntityManager 教程
- Spring Boot Data JPA 派生的查询
- Spring Boot Data JPA 查询示例
- Spring Boot Jersey 教程
- Spring Boot CSV 教程
- SpringBootServletInitializer教程
- 在 Spring Boot 中加载资源
- Spring Boot H2 REST 教程
- Spring Boot RestTemplate
- Spring Boot REST XML 教程
- Spring Boot Moustache 教程
- Spring Boot Thymeleaf 配置
- Spring Boot 自动控制器
- Spring Boot FreeMarker 教程
- Spring Boot Environment
- Spring Boot Swing 集成教程
- 在 Spring Boot 中提供图像文件
- 在 Spring Boot 中创建 PDF 报告
- Spring Boot 基本注解
- Spring Boot @ResponseBody教程
- Spring Boot @PathVariable教程
- Spring Boot REST Data JPA 教程
- Spring Boot @RequestParam教程
- Spring Boot 列出 bean
- Spring Boot @Bean
- Spring Boot @Qualifier教程
- 在 Spring Boot 中提供静态内容
- Spring Boot Whitelabel 错误
- Spring Boot DataSourceBuilder 教程
- Spring Boot H2 教程
- Spring Boot Web JasperReports 集成
- Spring Boot iText 教程
- Spring Boot cmd JasperReports 集成
- Spring Boot RESTFul 应用
- Spring Boot 第一个 Web 应用
- Spring Boot Groovy CLI
- Spring Boot 上传文件
- Spring Boot @ExceptionHandler
- Spring Boot @ResponseStatus
- Spring Boot ResponseEntity
- Spring Boot @Controller
- Spring Boot @RestController
- Spring Boot @PostConstruct
- Spring Boot @Component
- Spring Boot @ConfigurationProperties教程
- Spring Boot @Repository
- Spring Boot MongoDB 教程
- Spring Boot MongoDB Reactor 教程
- Spring Boot PostgreSQL 教程
- Spring Boot @ModelAttribute
- Spring Boot 提交表单教程
- Spring Boot Model
- Spring Boot MySQL 教程
- Spring Boot GenericApplicationContext
- SpringApplicationBuilder教程
- Spring Boot Undertow 教程
- Spring Boot 登录页面教程
- Spring Boot RouterFunction 教程
- ZetCode Symfony 教程
- Symfony DBAL 教程
- Symfony 表单教程
- Symfony CSRF 教程
- Symfony Vue 教程
- Symfony 简介
- Symfony 请求教程
- Symfony HttpClient教程
- Symfony Flash 消息
- 在 Symfony 中发送邮件
- Symfony 保留表单值
- Symfony @Route注解教程
- Symfony 创建路由
- Symfony 控制台命令教程
- Symfony 上传文件
- Symfony 服务教程
- Symfony 验证教程
- Symfony 翻译教程