QT Workshop

~ Chris Miles

Links

  1. QT Reference Documentation
  2. Linux Starter Code
    1. window.h
    2. window.cpp
    3. glwindow.h
    4. glwindow.cpp
    5. makefile
  3. Windows Demo - libs: qt-mt230nc.lib qtmain.lib qutil.lib
  4. Windows Code - Don't build on it, but it might have stuff worth learning from. This is qt 2.3 though so a lot of the classes are different now, and its on windows so compiling it is horrendous.

Why should you learn QT?

Answering this is best answered by explaining what QT is.

Q T is a professional graphical toolkit. Most every program that has a gui to it is based upon some kind of gtk. Whether it is the windows api's, Java swing/awt, GDK, QT, or raw X11. They all have a lot in common, in terms of classes provided and functionality. Some are easier then others, and some are prettier then others, but once you have learned one going to another is trivial.. In contrest glut is not a professional gtk, it is meant to provide a cross platform skeletal framework around a GL rendering context. Which it does, but its usefuless is limited to small gl projects, like pong.

Anyone who still wants to stick with glut should realize 3 things.

  1. Glut is ugly: Any project using something cleaner will look better on demo day.
  2. Glut has minimum input capabilities: Allowing users to designate which object they want to create and which color to make it is well beyond its utility. This puts you between having huge ugly menus or writing complicated classes already provided in qt.
  3. Glut is procedural, glut is written in standard c style, with a list of functions in one big file. This leads to hideous undreadable code as people mix c and c++.

What is different about QT

  1. QT has all the windowing widgets you use everyday. Buttons, labels, menubars, drag and drop and everything else. It is all very well done, and any projects you do will have a solid professional look to them.
  2. QT has some nice GL functions for rendering text effeciently and importing textures from a variety of formats.
  3. QT has a very strong set of non windowing classes to use. It has almost all the useful java classes without alot of the clutter.
  4. QT has the best input methods. Anything to do with the keyboard or mouse is awesome. Includes the important key release events missing from glut.
  5. QT has some very nice debugging features. QT code tends to output useful messages, versus core dumping or just not working at all (glorious black void).
  6. Signals and Slots allow for some beautiful code that tends to get ugly in other gtk's.
  7. Signals and Slots are however a hack ontop of c++. They make compilation tricky. Ontop of that g++ is quite slow at compiling QT, im not sure why it alone has issues, I have heard its from lack of pre compiling header files but I think its something more. Expect 10-15 second compile times per object file.
  8. QT is professional, it has the feel of something you spend several thousand dollars for (which you do if you use windows).

Learning QT

90% of learning qt is just learning a general idea of what classes do what and how to look them up in the documentation to use them.

The other 10% is compiling.

Since this is for a relatively limited set of projects I'll keep things related to them

QT/GL overview

In glut you create a window, intialize the gl and then delagate the running of things to either an idle function or preferably a pair of timer driven functions (a draw and update world function).

In QT you will do something similar. Just that instead of making an blank window to put your gl stuff in you will make a much more powerful window class you can attach things too. This class should hold the vast majority of the qt code you have to do. Which pretty much boils down to initializing widgets and connecting them to functions in the glwindow to call.

Inside the major window you will want a window for the GL stuff to be displayed in, this requires initializing a bunch of buffers, linking things up, etc etc. But its all nicely handled for you, just superclass from QGLWidget and override 3 functions.

I have written some code for you to get started with, I would highly recommend it. Not just to look at and write your own on the side, but as a place to start. It has a good architecture to build upon, some examples of useful stuff which you can easily remove, and a very powerful makefile.

QT basics

I am going to do a quick overview of the concepts and classes below and then get right into code. Most everything below has an example in the code so it would be best to start there. This is an excellent place to look through if you are trying to get something in particular to work.

SIGNALS and SLOTS.

these are beautiful for reducing linkage. A slot is a function..its just got the extra public slot: under its typing. A signal is something a class can emit, for example a push button emits clicked when it is pressed. You can use connect to like the signal to a slot, so whenever that signal is emitted, a cooresponding function is called. So when the button is pushed, some function is called. Its easy and powerful.

The syntax is: connect( button, SIGNAL( clicked()), this, SLOT( buttonClicked()))

button is a pointer to the object emitting the signal
clicked() is the type of the signal (some signals emit things with values so it could be clicked(int))
this is a pointer to the object
SLOT( buttonClicked()) is the function to call.

QT stuff to know. There are about a dozen classes you really need to know to use qt. I'll explain what they do and which functions to know as well as a good constructor to use(there are usually several complicated constructors with tons of default parameters)

QWidget

This is the base class for anything you want to have its own viewport. From your main your main window down to the smallest icons. This has a zillion functions, but you wont need the huge majority of them.

  1. QWidget(parent, name) -> parent is your parent class (QT keeps a hierarchy of its classes for you, so when you delete one it deletes all its children. Very nice. Name -> some name for it, use whatever identifies this instantiation for you since it will use this for debugging info.
  2. setMinimum/MaximumSize -> if you only want it to be of a certain size.
  3. width/height -> current size of the window (for translating mouse clicks into world space).

QGLWidget

Similar to a qwidget, only that it allows for GL functioncalls. There are 3 functions you need to implement for it to work, as well as some convenient ones for you to use.

  1. GLWidget() -> same as widget
  2. initailizeGL() -> Called when the GL buffers are first setup. Put all your initialization stuff here.
  3. paintGL() -> call all your drawing functions here -> connect a timer to updateGL() to get a nice constant framerate.
  4. resizeGL() -> called when the window resizes, put any resizing stuff here (viewport changes).
  5. renderText( x,y,z, String ) -> renders the string in world coordinates at x,y,z. These two are optimized through display lists so its faster then the glut version.
  6. renderText( x,y, String ) -> renders the string in window coordinates at x,y.

QLabel

A Qlabel is just an image or text somewhere that has no interaction associated with it.

  1. QLabel* label = new QLabel( "hi world", this )
  2. QLabel("text", parent) -> creates a label with the text in it.
  3. QLabel( new QPixmap( filename), parent ) creates a label with that pixmap

QPushButton

Just a simple button with text or an icon. Emits clicked() when clicked.

  1. QPushButton* push = new QPushButton( "&Push ME", this); //push me -> the text displayed // &P -> Alt-P activates this button// this -> its parent
  2. push->setPixmap( new QPixmap("filename")) // sets the button to an image found in the filename.
  3. push->.setText ( text ) // displays text instead of a button.
  4. connect( push, SIGNAL( clicked()), this, SLOT( pushClicked()))) //connect it so it calls a function of yours when pressed.

QMenubar / QPopupMenu

QMenu bar is the actual bar across the top, it holds a bunch of popup menus.
QPopupMenu is a menu that pops up somewhere (only going to cover there use in menus.

QMenubar* menubar = new QMenubar
QPopupMenu* fileMenu = new QPopupMenu
fileMenu->insertItem("&Save", this, SLOT(save()), CTRL + Key_N ); //adds a new button to the file menu
menubar->insertItem( fileMenu ) //adds the popupmenu to the menubar
layout->setMenuBar( menubar ) // neccessary to keep it from overlaping with things

QVBoxLayout / QHBoxLayout

Your window class will need a layout of some kind. The box layouts represent vertical and horizontal orderings of them. Used iteratively they are very effective. So if you want a main window, with a panel of buttons on the side you create a Horizontal box that holds the main window and another layout, the second layout being a vertical sorting of buttons.

QHBoxLayout( this ) -> to create your main layout
QVBoxLayout( hboxlayout ) -> to put this layout inside the other one.
addWidget( Widget* w ) -> adds w to this layout.
addStretch( int position, int stretchiness ) -> inserts some empty space in teh position, stretchiness determines its willingness to stretch (use 1).
addStretch( -1, 1 ) -> Will keep all your empty space at the end of the layout.

QGridLayout

Compareable to a Java gridbag layout, it holds widgets in a grid of rows and columns. This is the most powerful layout, but it can be tricky.

addWidget( Widget* w, int row, int column )
addMultiCellWidget( w, int fromRow, int toRow, int fromColumn, int toColumn ) Adds a widget that takes up multiple rows and columns, instead of doing the two box layouts you can use one grid layout, and put the buttons in different cells on the side, and then have the main widget occupy all the cells to the side of them.
addItem / addMultiCellItem similar to the widget adds only they add layouts.

Widgets you might want to use I am not going to cover.

QRadioButton / Button Group -> Almost identical to QPushButton, just you put the button's in a button group and only one can be selected at a time.

QColorDialog -> Its a big dialog for choosing colors, its new though so ive never used it.

Other QT classes you should definitely use.

QString -> its a string, comparable to Java::string. Only some of the nice language supported features(toString). Replace all your char*'s with it.

  1. .arg( a ) -> similar to printf QString("player %1 -> %2").arg(1).arg(3) = "player 1 -> 3" //weird but very convenient once you get used to it. They are numbered though versus typed. can put pretty much anything in for a.
  2. ascii() -> returns a char* for this string (QString is unicode).
  3. number( a ) -> creates a string = that number, whatever its type is.
  4. << >>. These can be fed into any of the streams (ie. network streams).

QStrList -> An extension of QValueList<String>

  1. Split( "-", "hello-world" ) -> split, like the perl split. Accepts regular expressions. Awesome.

Q[Value/Ptr][List/Queue/Stack/Dict/Vector] all the data types you could want. Personally I use the two vectors for most everything. Dictionaries are very nice if you have use for them though (hash map).

QPtr stuff specifically keeps a pointer to the data, and can be set to autodelete it for you. This is very nice, as it allows you to keep other pointers synchonized to list elements, without having to keep track of when to delete things. I generally don't use them though.

Q Debugging functions

qFatal( char* s)// kills the program and outputs s, s is essentailly a printf call

qWarning( char* s )//similar only it doesn't kill the program

Q_CHECKPTR( void* v ) //outputs a nice debugging message if v is null (use htis whenever you allocate memory ).