ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 布局管理 > 原文: [http://zetcode.com/gui/csharpqyoto/layoutmanagement/](http://zetcode.com/gui/csharpqyoto/layoutmanagement/) 在 Qyoto C# 编程教程的这一部分中,我们将介绍布局管理器。 在设计应用的 GUI 时,我们决定要使用哪些组件以及如何在应用中组织这些组件。 为了组织我们的组件,我们使用专门的不可见对象,称为布局管理器。 Qyoto 中有多个选项。 我们可以使用绝对定位,内置布局管理器或创建自定义布局管理器。 我们还可以使用 Qt Designer 直观地构建布局。 Qyoto 有一些重要的内置布局管理器。 `QVBoxLayout`类垂直排列小部件。 `QHBoxLayout`水平排列小部件。 `QGridLayout`类将小部件布置在网格中。 网格布局是最灵活的布局管理器。 框布局可以相互嵌套以创建复杂的布局。 ## 绝对定位 在大多数情况下,程序员应使用布局管理器。 在某些情况下,我们可以使用绝对定位。 在绝对定位中,程序员以像素为单位指定每个小部件的位置和大小。 如果调整窗口大小,则窗口小部件的大小和位置不会改变。 应用在各种平台上看起来都不同,在 Linux 上看起来不错,在 Mac 上看起来不好。 在应用中更改字体可能会破坏布局。 如果将应用翻译成另一种语言,则必须重做布局。 对于所有这些问题,仅在有理由时才使用绝对定位。 ```cs using System; using QtCore; using QtGui; /** * ZetCode Qyoto C# tutorial * * In this program, we lay out widgets * using absolute positioning * * @author Jan Bodnar * website zetcode.com * last modified October 2012 */ public class QyotoApp : QWidget { public QyotoApp() { WindowTitle = "Absolute"; InitUI(); Resize(300, 280); Move(300, 300); Show(); } void InitUI() { StyleSheet = "QWidget { background-color: #414141 }"; QPixmap bardejov = new QPixmap("bardejov.jpg"); QPixmap rotunda = new QPixmap("rotunda.jpg"); QPixmap mincol = new QPixmap("mincol.jpg"); QLabel barLabel = new QLabel(this); barLabel.Pixmap = bardejov; barLabel.Move(20, 20); QLabel rotLabel = new QLabel(this); rotLabel.Pixmap = rotunda; rotLabel.Move(40, 160); QLabel minLabel = new QLabel(this); minLabel.Pixmap = mincol; minLabel.Move(170, 50); } [STAThread] public static int Main(String[] args) { new QApplication(args); new QyotoApp(); return QApplication.Exec(); } } ``` 在此示例中,我们使用绝对定位显示了三幅图像。 ```cs StyleSheet = "QWidget { background-color: #414141 }"; ``` `StyleSheet`属性用于更改窗口工作区的背景颜色。 ```cs QLabel barLabel = new QLabel(this); barLabel.Pixmap = bardejov; ``` `QLabel`小部件用于保存图像。 ```cs barLabel.Move(20, 20); ``` 我们使用`Move()`方法将标签放置在窗口上的`x = 20`,`y = 20`处。 调整窗口大小时,标签将保留其初始大小。 ![Absolute](https://img.kancloud.cn/63/e8/63e88aeb6c03c3e72bc782f698a04024_302x306.jpg) 图:绝对定位 ## 按钮示例 在下面的示例中,我们将在窗口的右下角放置两个按钮。 ```cs using System; using QtCore; using QtGui; /** * ZetCode Qyoto C# tutorial * * In this program, use box layouts * to position two buttons in the * bottom right corner of the window. * * @author Jan Bodnar * website zetcode.com * last modified October 2012 */ public class QyotoApp : QWidget { public QyotoApp() { WindowTitle = "Buttons"; InitUI(); Resize(300, 150); Move(300, 300); Show(); } void InitUI() { QVBoxLayout vbox = new QVBoxLayout(this); QHBoxLayout hbox = new QHBoxLayout(); QPushButton ok = new QPushButton("OK", this); QPushButton apply = new QPushButton("Apply", this); hbox.AddWidget(ok, 1, AlignmentFlag.AlignRight); hbox.AddWidget(apply); vbox.AddStretch(1); vbox.AddLayout(hbox); } [STAThread] public static int Main(String[] args) { new QApplication(args); new QyotoApp(); return QApplication.Exec(); } } ``` 我们使用嵌套框布局来获得我们想要的布局。 ```cs QVBoxLayout vbox = new QVBoxLayout(this); QHBoxLayout hbox = new QHBoxLayout(); ``` 我们使用一个垂直框和一个水平框。 ```cs QPushButton ok = new QPushButton("OK", this); QPushButton apply = new QPushButton("Apply", this); ``` 这是两个将进入窗口右下角的按钮。 ```cs hbox.AddWidget(ok, 1, AlignmentFlag.AlignRight); ``` 我们将确定按钮放入水平框中。 第二个参数是`stretch`因子。 它将扩大分配给“确定”按钮的区域。 它会占用所有可用空间。 在此区域内,按钮向右对齐。 ```cs vbox.AddStretch(1); ``` 这条线创建了一个垂直扩展的白色空间,它将带有按钮的水平框推到底部。 ```cs vbox.AddLayout(hbox); ``` 水平框嵌套在垂直框中。 ![Buttons example](https://img.kancloud.cn/ab/08/ab08d15ae34552d3bc3a6966b3b1dbf9_308x177.jpg) 图:按钮示例 ## Windows 示例 以下是嵌套框布局更复杂的示例。 ```cs using System; using QtCore; using QtGui; /** * ZetCode Qyoto C# tutorial * * In this program, use box layouts * to create a windows example. * * @author Jan Bodnar * website zetcode.com * last modified October 2012 */ public class QyotoApp : QWidget { public QyotoApp() { WindowTitle = "Windows"; InitUI(); Resize(350, 300); Move(300, 300); Show(); } void InitUI() { QVBoxLayout vbox = new QVBoxLayout(this); QVBoxLayout vbox1 = new QVBoxLayout(); QHBoxLayout hbox1 = new QHBoxLayout(); QHBoxLayout hbox2 = new QHBoxLayout(); QLabel windLabel = new QLabel("Windows", this); QTextEdit edit = new QTextEdit(this); edit.Enabled = false; QPushButton activate = new QPushButton("Activate", this); QPushButton close = new QPushButton("Close", this); QPushButton help = new QPushButton("Help", this); QPushButton ok = new QPushButton("OK", this); vbox.AddWidget(windLabel); vbox1.AddWidget(activate); vbox1.AddWidget(close, 0, AlignmentFlag.AlignTop); hbox1.AddWidget(edit); hbox1.AddLayout(vbox1); vbox.AddLayout(hbox1); hbox2.AddWidget(help); hbox2.AddStretch(1); hbox2.AddWidget(ok); vbox.AddLayout(hbox2, 1); Layout = vbox; } [STAThread] public static int Main(String[] args) { new QApplication(args); new QyotoApp(); return QApplication.Exec(); } } ``` 在此布局中,我们使用两个垂直和水平框。 ```cs QVBoxLayout vbox = new QVBoxLayout(this); ``` 这是示例的基本布局。 ```cs vbox.AddWidget(windLabel); ``` 首先是标签小部件。 它只是转到垂直框的顶部。 ```cs vbox1.AddWidget(activate); vbox1.AddWidget(close, 0, AlignmentFlag.AlignTop); hbox1.AddWidget(edit); hbox1.AddLayout(vbox1); vbox.AddLayout(hbox1); ``` 在窗口的中心部分,我们有一个文本编辑小部件和两个垂直排列的按钮。 这些按钮进入垂直框。 在此垂直框中,按钮与顶部对齐。 垂直框和文本编辑进入水平框。 该水平框转到标签窗口小部件正下方的基本垂直框。 ```cs hbox2.AddWidget(help); hbox2.AddStretch(1); hbox2.AddWidget(ok); vbox.AddLayout(hbox2, 1); ``` 帮助和确定按钮进入另一个水平框。 这两个按钮之间有一个扩大的空白区域。 同样,水平框转到基本垂直框。 ```cs Layout = vbox; ``` 基本的垂直框设置为窗口的主要布局。 ![Windows example](https://img.kancloud.cn/f2/86/f286db8cc99510f1ab6b1ac4d20aa5f3_352x326.jpg) 图:窗口示例 ## 新文件夹示例 在最后一个示例中,我们使用`QGridLayout`管理器创建“新文件夹”布局示例。 ```cs using System; using QtCore; using QtGui; /** * ZetCode Qyoto C# tutorial * * In this program, use the QGridLayout manager * to create a New Folder example. * * @author Jan Bodnar * website zetcode.com * last modified October 2012 */ public class QyotoApp : QWidget { public QyotoApp() { WindowTitle = "New Folder"; InitUI(); Resize(300, 300); Move(300, 300); Show(); } void InitUI() { QGridLayout grid = new QGridLayout(this); QLabel nameLabel = new QLabel("Name", this); QLineEdit nameEdit = new QLineEdit(this); QTextEdit text = new QTextEdit(this); QPushButton okButton = new QPushButton("OK", this); QPushButton closeButton = new QPushButton("Close", this); grid.AddWidget(nameLabel, 0, 0); grid.AddWidget(nameEdit, 0, 1, 1, 3); grid.AddWidget(text, 1, 0, 2, 4); grid.SetColumnStretch(1, 1); grid.AddWidget(okButton, 4, 2); grid.AddWidget(closeButton, 4, 3); } [STAThread] public static int Main(String[] args) { new QApplication(args); new QyotoApp(); return QApplication.Exec(); } } ``` 在我们的示例中,我们有一个标签,一行编辑,一个文本编辑和两个按钮。 ```cs QGridLayout grid = new QGridLayout(this); ``` 我们创建`QGridLayout`管理器的实例。 ```cs grid.AddWidget(nameLabel, 0, 0); ``` 我们将标签小部件放置在网格的第一个单元格中。 单元格从 0 开始计数。最后两个参数是行号和列号。 ```cs grid.AddWidget(nameEdit, 0, 1, 1, 3); ``` 线编辑窗口小部件位于第一行第二列。 最后两个参数是行跨度和列跨度。 在水平方向上,小部件将跨越三列。 ```cs grid.SetColumnStretch(1, 1); ``` 该方法的参数是列号和拉伸因子。 在这里,我们将拉伸因子 1 设置到第二列。 这意味着此列将占用所有剩余空间。 之所以这样设置,是因为我们希望按钮保持其初始大小。 ![New Folder example](https://img.kancloud.cn/5e/33/5e33b22065166e0658223c82b6273c8c_308x327.jpg) 图:新文件夹 example 在 Qyoto C# 教程的这一部分中,我们提到了小部件的布局管理。