QtJambi 中的自定义小部件
在 QtJambi 编程教程的这一部分中,我们将创建一个自定义小部件。
工具箱通常仅提供最常见的窗口小部件,例如按钮,文本窗口小部件,滑块等。没有工具箱可以提供所有可能的窗口小部件。 程序员必须自己创建此类小部件。 他们使用工具箱提供的绘图工具来完成此任务。 有两种可能性。 程序员可以修改或增强现有的小部件。 或者,他可以从头开始创建自定义窗口小部件。
刻录小部件
在下一个示例中,我们将创建一个自定义刻录小部件。 可以在 Nero 或 K3B 之类的应用中看到此小部件。 该小部件将从头开始创建。
Burning.java
package com.zetcode;
import com.trolltech.qt.core.QPointF;
import com.trolltech.qt.core.QRectF;
import com.trolltech.qt.gui.QBrush;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QFont;
import com.trolltech.qt.gui.QFontMetrics;
import com.trolltech.qt.gui.QLineF;
import com.trolltech.qt.gui.QPaintEvent;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QWidget;
public class Burning extends QWidget {
private final int PANEL_HEIGHT = 30;
private final int DISTANCE = 19;
private final int LINE_WIDTH = 5;
private final int DIVISIONS = 10;
private final float FULL_CAPACITY = 700f;
private final float MAX_CAPACITY = 750f;
private final QColor redColor = new QColor(255, 175, 175);
private final QColor yellowColor = new QColor(255, 255, 184);
private QWidget parent;
private String num[] = {
"75", "150", "225", "300",
"375", "450", "525", "600",
"675"
};
public Burning(QWidget parent) {
super(parent);
this.parent = parent;
setMinimumHeight(PANEL_HEIGHT);
}
@Override
protected void paintEvent(QPaintEvent event) {
QPainter painter = new QPainter(this);
drawWidget(painter);
painter.end();
}
protected void drawWidget(QPainter painter) {
JambiApp burn = (JambiApp) parent;
float width = size().width();
float slid_width = burn.getCurrentWidth();
float step = width / DIVISIONS;
float till = (width / MAX_CAPACITY) * slid_width;
float full = (width / MAX_CAPACITY) * FULL_CAPACITY;
if (slid_width > FULL_CAPACITY) {
painter.setPen(yellowColor);
painter.setBrush(yellowColor);
painter.drawRect(new QRectF(0, 0, full, PANEL_HEIGHT));
painter.setPen(redColor);
painter.setBrush(redColor);
painter.drawRect(new QRectF(full+1, 0, till-full, PANEL_HEIGHT));
} else {
if (slid_width > 0) {
painter.setPen(yellowColor);
painter.setBrush(yellowColor);
painter.drawRect(new QRectF(0, 0, till, PANEL_HEIGHT));
}
}
painter.setPen(new QColor(90, 90, 90));
painter.setBrush(QBrush.NoBrush);
painter.drawRect(0, 0, size().width()-1, PANEL_HEIGHT-1);
QFont newFont = font();
newFont.setPointSize(7);
painter.setFont(newFont);
for (int i = 1; i <= num.length; i++) {
painter.drawLine(new QLineF(i*step, 1, i*step, LINE_WIDTH));
QFontMetrics metrics = new QFontMetrics(newFont);
int w = metrics.width(num[i-1]);
painter.drawText(new QPointF(i*step-w/2, DISTANCE), num[i-1]);
}
}
}
在这个文件中,我们创建了刻录小部件。
public class Burning extends QWidget {
自定义窗口小部件基于QWidget
小部件。
private final int PANEL_HEIGHT = 30;
private final int DISTANCE = 19;
private final int LINE_WIDTH = 5;
private final int DIVISIONS = 10;
private final float FULL_CAPACITY = 700f;
private final float MAX_CAPACITY = 750f;
这些是重要的常数。 PANEL_HEIGHT
定义自定义窗口小部件的高度。 DISTANCE
是比例尺上的数字与其父边框顶部之间的距离。 LINE_WIDTH
是垂直线的宽度。 DIVISIONS
是秤的数量。 FULL_CAPACITY
是媒体的容量。 达到目标后,就会发生过度刻录。 用红色显示。 MAX_CAPACITY
是介质的最大容量。
private String num[] = {
"75", "150", "225", "300",
"375", "450", "525", "600",
"675"
};
我们使用这些数字来构建刻录小部件的比例。
@Override
protected void paintEvent(QPaintEvent event) {
QPainter painter = new QPainter(this);
drawWidget(painter);
painter.end();
}
自定义窗口小部件的图形委托给drawWidget()
方法。
JambiApp burn = (JambiApp) parent;
我们检索对父窗口小部件的引用。
float slid_width = burn.getCurrentWidth();
我们使用它来获取当前选定的滑块值。
float width = size().width();
我们得到小部件的宽度。 自定义窗口小部件的宽度是动态的。 用户可以调整大小。
float till = (width / MAX_CAPACITY) * slid_width;
float full = (width / MAX_CAPACITY) * FULL_CAPACITY;
我们使用width
变量进行转换。 在比例尺值和自定义小部件的度量之间。 请注意,我们使用浮点值。 我们在绘图中获得了更高的精度。
painter.setPen(redColor);
painter.setBrush(redColor);
painter.drawRect(new QRectF(full+1, 0, till-full, PANEL_HEIGHT));
这三行画出红色矩形,表示过度燃烧。
painter.drawRect(0, 0, size().width()-1, PANEL_HEIGHT-1);
这是小部件的周长。 外部矩形。
painter.drawLine(new QLineF(i*step, 1, i*step, LINE_WIDTH));
在这里,我们画出小的垂直线。
int w = metrics.width(num[i-1]);
painter.drawText(new QPointF(i*step-w/2, 19), num[i-1]);
在这里,我们绘制刻度的数字。 为了精确定位数字,我们必须获得字符串的宽度。
JambiApp.java
package com.zetcode;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QFrame;
import com.trolltech.qt.gui.QHBoxLayout;
import com.trolltech.qt.gui.QSlider;
import com.trolltech.qt.gui.QVBoxLayout;
import com.trolltech.qt.gui.QWidget;
/**
* ZetCode QtJambi tutorial
*
* In this program, we create
* a custom widget
*
* @author jan bodnar
* website zetcode.com
* last modified March 2009
*/
public class JambiApp extends QFrame {
private final int MAX_CAPACITY = 750;
QSlider slider;
QWidget widget;
int cur_width;
public JambiApp() {
setWindowTitle("The Burning Widget");
initUI();
resize(370, 200);
move(300, 300);
show();
}
private void initUI() {
slider = new QSlider(Qt.Orientation.Horizontal , this);
slider.setMaximum(MAX_CAPACITY);
slider.setGeometry(50, 50, 130, 30);
slider.valueChanged.connect(this, "valueChanged(int)");
QVBoxLayout vbox = new QVBoxLayout(this);
QHBoxLayout hbox = new QHBoxLayout();
vbox.addStretch(1);
widget = new Burning(this);
hbox.addWidget(widget, 0);
vbox.addLayout(hbox);
setLayout(vbox);
}
public void valueChanged(int val) {
cur_width = val;
widget.repaint();
}
public int getCurrentWidth() {
return cur_width;
}
public static void main(String[] args) {
QApplication.initialize(args);
new JambiApp();
QApplication.exec();
}
}
这是主文件。 在这里,我们创建滑块小部件并使用我们的自定义小部件。
widget = new Burning(this);
hbox.addWidget(widget, 0);
我们创建了刻录小部件的实例,并将其添加到水平框中。
public void valueChanged(int val) {
cur_width = val;
widget.repaint();
}
当滑块的值更改时,我们将其存储在cur_width
变量中,然后重新绘制自定义窗口小部件。
public int getCurrentWidth() {
return cur_width;
}
定制小部件调用此方法以获取实际的滑块值。
图:刻录小部件
在 QtJambi 教程的这一部分中,我们演示了如何创建自定义窗口小部件。