Sunday, October 29, 2006

qt4 for full-featured rapid prototypes



Note: The title bar is missing from the screenshot since KDE's screenshot utility doesn't see the beryl-rendered title bar - yet. However, I can assure you that the sample code renders and runs properly on linux and windows.

I've been working in qt4 for a few months now and I'm really starting to enjoy it. After some crashes in qt designer with the 4.1 release, I've upgraded to 4.2 and abandoned the designer completely.

Some people look at me like I'm crazy when I explain that I won't use the tool unless it's reliable. I can see them thinking... what? you're going to turn back the clock 15 years? Even then, I think qt designer's usability is poor, at best. Just try editing rows and columns in a table or tree view. Truly painful. Why not just let me manipulate the data in the rows and columns directly? How a modal dialog will ever be a better solution than direct manipulation is beyond me.

But I digress. My real point here was to offer some code that demonstrates qt's power, high level API, and ease-of-use, which makes my maniacal code hacking is better than designing resources method look like real fun. It's where the rubber meets the road. One of the beautiful things about qt is that it leaves the declarative vs. imperative choice up to the implementor.

What's not clear is why so many of the samples are so damned convoluted. Oh sure, this isn't the kind of well-structured c++ that you'd put in a shipping app, but I'm talking about going from concept to wireframe to prototype in a day.

If you thought a full-featured app with title bar, menu, tool bar, status bar, docks, tool boxes and an MDI workspace, mostly layout managed with clearly defined UI physics required a bunch of drag and drop in the designer, or more than a hundred lines of code, think again:


#include <qapplication>
#include <qfile>
#include <qtgui>

QWidget * makeNewMdiChild( void )
{
QGridLayout * mdiChildLayout = new QGridLayout;
QWidget * mdiChild = new QWidget;
QScrollArea *sa = new QScrollArea;
QLabel *imageLabel = new QLabel;
QImage image("/home/david/264287866_f7001afc44_o.jpg");
imageLabel->setPixmap(QPixmap::fromImage(image));
sa->setWidgetResizable( true );
sa->setWidget( imageLabel );
mdiChildLayout->addWidget(sa);
mdiChild->setLayout(mdiChildLayout);
return mdiChild;
}

int main( int argc, char ** argv )
{
int rc = 0;
QApplication a(argc, argv);
QMainWindow w;
QTextEdit edit;
QWorkspace workSpace;
w.setCentralWidget(&workSpace);
QWidget * mdiChild = makeNewMdiChild();
workSpace.addWindow(mdiChild);
w.setWindowTitle("Hello Dock");
QMenuBar menuBar;
menuBar.addMenu("&File");
menuBar.addMenu("&Edit");
menuBar.addMenu("&View");
menuBar.addMenu("&Help");
w.setMenuBar(&menuBar);
QStatusBar statusBar;
statusBar.showMessage("Status Bar");
w.setStatusBar(&statusBar);
QToolBar toolBar("Tool Bar");
QAction* tileAction = new QAction("Tile", &w);
toolBar.connect(tileAction, SIGNAL(triggered()), &workSpace, SLOT(tile()));
toolBar.addAction(tileAction);
w.addToolBar(&toolBar);
QDockWidget leftDock("Left Dock", &w);
QGridLayout leftDockLayout1;
QWidget leftDockWidget1;
QToolBox tb1(&leftDock);
QLineEdit leftEdit1;
QWidget leftDockWidget2;
QGridLayout leftDockLayout2;
QLineEdit leftEdit2;
leftDockLayout1.addWidget(&leftEdit1);
leftDockWidget1.setLayout(&leftDockLayout1);
leftDockLayout2.addWidget(&leftEdit2);
leftDockWidget2.setLayout(&leftDockLayout2);
tb1.addItem(&leftDockWidget1, "toolbox1");
tb1.addItem(&leftDockWidget2, "toolbox2");
leftDock.setWidget(&tb1);
QDockWidget rightDock("Right Dock", &w);
QGridLayout rightDockLayout;
QWidget rightDockWidget;
QLineEdit rightEdit;
rightDockLayout.addWidget(&rightEdit);
rightDockWidget.setLayout(&rightDockLayout);
rightDock.setWidget(&rightDockWidget);
QDockWidget topDock("Top Dock", &w);
QGridLayout topDockLayout;
QWidget topDockWidget;
QLineEdit topEdit;
topDockLayout.addWidget(&topEdit);
topDockWidget.setLayout(&topDockLayout);
topDock.setWidget(&topDockWidget);
QDockWidget bottomDock("Bottom Dock", &w);
QGridLayout bottomDockLayout;
QWidget bottomDockWidget;
QLineEdit bottomEdit;
bottomDockLayout.addWidget(&bottomEdit);
bottomDockWidget.setLayout(&bottomDockLayout);
bottomDock.setWidget(&bottomDockWidget);
w.addDockWidget(Qt::LeftDockWidgetArea, &leftDock);
w.addDockWidget(Qt::RightDockWidgetArea, &rightDock);
w.addDockWidget(Qt::TopDockWidgetArea, &topDock);
w.addDockWidget(Qt::BottomDockWidgetArea, &bottomDock);
w.show();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
rc = a.exec();
return rc;
}

0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home