csci 104 qt intro mark redekopp david kempe. 2 © copyright 2013 brent nash & mark redekopp, all...

Download CSCI 104 Qt Intro Mark Redekopp David Kempe. 2 © Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt  What is QT? –Pronounced “cute” –An

If you can't read please download the document

Upload: chrystal-wilson

Post on 26-Dec-2015

216 views

Category:

Documents


4 download

TRANSCRIPT

  • Slide 1
  • CSCI 104 Qt Intro Mark Redekopp David Kempe
  • Slide 2
  • 2 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt What is QT? Pronounced cute An cross-platform application development framework built by Nokia A toolkit for building Graphical User Interfaces (GUIs) GUI toolkits are composed of many classes including many widgets "Widget" is GUI-lingo for a 'control' or graphical component that a user can interact with QT has bindings available for many languages C++, Python, Ruby, Java, etc. We are using QT v4.8.1
  • Slide 3
  • 3 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QApplication Every major QT widget has its own header See QPushButton in the example QApplication The main class that controls all the default GUI behavior and manages application resources Every QT GUI application must have a QApplication instance (and only one!) QApplication parses the command line input and pulls out any display-related parameters A QApplication must be created before any GUI-related features can be used #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Hello world!"); button.show(); return app.exec(); }
  • Slide 4
  • 4 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QPushButton QPushButton A button object that you can click on QPushButton button("Hello World!"); Creates a clickable button on the GUI We can only do this now that we already created a QApplication to handle all the backend stuff The button is clickable just by nature The button will have the text Hello World on it There are all kinds of button function/display attributes we could set if we really wanted to Color, Size, Text/Image, Animation, Border, etc. #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Hello world!"); button.show(); return app.exec(); }
  • Slide 5
  • 5 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Display Widgets button.show(); Widgets are always invisible by default when they are created, you must call show() to display them Calling show() on a widget also calls show on all the widgets it contains (all of its children) Some widgets are merely containers for other widgets (i.e. a display grid that display other widgets in some tabular format) #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Hello world!"); button.show(); return app.exec(); }
  • Slide 6
  • 6 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Event-Driven Program Flow return app.exec(); At this point, main() passes control to the QT framework exec() will not return until the window is terminated Question? What happens to your code flow? How do you get any other code to run? Welcome to the world of event-driven programs You write code (member functions) that is 'automatically' called/executed when an event occurs (e.g. click(), resize(), mouseOver(), ) More on this later... #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Hello world!"); button.show(); return app.exec(); }
  • Slide 7
  • 7 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved End Result All of this results in #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("Hello world!"); button.show(); return app.exec(); }
  • Slide 8
  • 8 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Compiling Qt Applications We can't just type 'g++ -o qtex qtex.cpp'. Why? We have external dependencies that aren't part of standard C++ How will the compiler find the QT.h files? How will the linker find the QT compiled code? QT has to build Meta-Objects to handle communication between GUI pieces The individual.cpp files need to compile and link separately in some cases 'make' and 'qmake' to the rescue We've seen 'make' which helps us specify dependencies, compile order, and compiler commands 'qmake' will examine code in the current directory and help to automatically generate a 'Makefile'
  • Slide 9
  • 9 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved 3-Step Qt Compiler Process Step 1: Generate a Qt project file with 'qmake' $ qmake project The command will make Qt examine all the source code in the current directory and make a platform-independent project file (with a.pro extension) that specifies dependencies between your.h and.cpp files Step 2: Generate the platform dependent Makefile $ qmake This command will make QT read the.pro file from the current directory and generate a Makefile that contains all the commands for compiling the code and linking it with the QT libraries Step 3: Run 'make' $ make If you have any compiler or linker errors, this is the step in the process where you will see them If you only need to recompile, you only need to use this particular step of the 3 step process
  • Slide 10
  • 10 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Compilation Notes Keep each project in a separate directory (this is why we can run qmake with no arguments) If you add new.h or.cpp files, you need to re-run the entire compilation process (i.e. Make new.pro and Makefile files again) If your object needs slots or signals, then you MUST put it into separate.h and.cpp files If you're getting weird linker errors, try make clean or try rebuilding the.pro file and the Makefile You may notice that when you compile some projects with QT, it actually generate extra.cpp files These extra files are generated by QT's moc (Meta Object Compiler) QT makes extensive use of the preprocessor to generate code that makes things like its signals and slots mechanisms work Don't bother changing these files. They'll just get overwritten next time you compile.
  • Slide 11
  • 11 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Organization For your programming purposes, the QT windowing framework consists of three major parts (in reality, it's MUCH more complicated than this): Widgets Layouts Signals & Slots
  • Slide 12
  • 12 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Widgets What is a widget? A user interface object that can process input, emit signals and draw graphics A widget can be styled to have a vastly different appearance than its default Most widgets generate signals that can be received by pieces of your code called slots QT comes pre-packaged with a ton of pre-made widgets to suit most of your GUI-building needs Buttons, Containers, Menus, etc.
  • Slide 13
  • 13 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Button Examples Push Buttons Tool Buttons Checkboxes Radio Buttons Images from http://doc.trolltech.com/4.3/gallery-macintosh.html
  • Slide 14
  • 14 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Container Examples Group BoxesTabbed Displays Scrolled DisplaysFrames Images from http://doc.trolltech.com/4.3/gallery-macintosh.html
  • Slide 15
  • 15 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved User Input Widget Examples Text Entry Combo Boxes Sliders Spin Boxes Calendars Images from http://doc.trolltech.com/4.3/gallery-macintosh.html
  • Slide 16
  • 16 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Layouts What is a layout? A layout describe how widgets are organized and positioned in a user interface The jobs of a QT layout Positioning of widgets in GUI Choosing sensible default and minimum sizes Handling window resize events Automatic updates when content changes Font size, text or other widget changes Add or removal of new widgets Showing and hiding of existing widgets
  • Slide 17
  • 17 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved More About Layouts QT layouts and widgets share numerous parent/child relationships Widgets can contain other widgets Widgets can have layouts Layouts can contain widgets Layouts can contain other layouts There can be a gigantic graph of parent and child relationships in a GUI The best way to make a complex layout is usually to combine many simpler layouts FYI: Getting a layout right is HARD
  • Slide 18
  • 18 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Sample Layouts QVBoxLayout Layout all children in a vertical column (top to bottom or bottom to top) QHBoxLayout Layout all children in a horizontal row (left to right or right to left) Images from http://qt.nokia.com/doc/4.5/layout.html
  • Slide 19 addWidget(button1); layout->addWidget(button2); layout->addWidget(button3); window->setLayout(layout); window->show(); return app.exec(); } Code from http://qt.nokia.com/doc/4.5/layout.html">
  • 19 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Layout Example Code #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget *window = new Qwidget; QPushButton *button1 = new QPushButton("One"); QPushButton *button2 = new QPushButton("Two"); QPushButton *button3 = new QpushButton("Three"); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(button1); layout->addWidget(button2); layout->addWidget(button3); window->setLayout(layout); window->show(); return app.exec(); } Code from http://qt.nokia.com/doc/4.5/layout.html
  • Slide 20
  • 20 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved More Layouts QGridLayout Layout widgets in a 2D grid Widgets can span multiple rows/columns QFormLayout Layout children in a 2-column descriptive label-field style. Images from http://qt.nokia.com/doc/4.5/layout.html
  • Slide 21
  • 21 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Event-Based Programming GUI-based programs follow a different paradigm than basic command line programs The window will sit there indefinitely until the user does something Your code no longer functions on line-by-line flow, it is triggered by events In QT, all widgets are capable of firing events and receiving events Signals are used to notify (emit) widgets of an event Slots are used to receive (listen for) widget events connect is used to tie together a signal & a slot Signals & slots can have M-to-N connections
  • Slide 22
  • 22 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Signals and Slots Signals and Slots provide communication between various object in your application Often when one widget changes, you need another widget to know about it A signal emitter and a slot receiver never need to know about each other! Widgets emit signals whether or not any other widgets are listening e.g. QPushButton has a clicked() signal Widgets slots listen for signals whether or not there are any being emitted A slot is just a normal class member function! e.g. Create a widget with a handleClick() slot
  • Slide 23
  • 23 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QT Signals & Slots Image from http://doc.trolltech.com/4.6/signalsandslots.html
  • Slide 24
  • 24 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Signal/Slot Example #include int main(int argc, char *argv[]) { QApplication app(argc, argv); QPushButton button("QUIT"); //connect(object1 pointer, object1 signal, // object2 pointer, object2 slot) QObject::connect(&button, SIGNAL(clicked()), &app, SLOT(quit())); button.show(); return app.exec(); } Code from http://qt.nokia.com/doc/4.5/layout.html
  • Slide 25
  • 25 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QT Signals & Slots Summary Using event-driven programming in QT involves three major parts: 1. A widget with a SIGNAL to emit events when they occur (e.g. clicked() on QPushButton) 2. A widget with a SLOT to receive events that have been emitted (e.g. quit() on QApplication) 3. A connect statement to wire the signal and slot together so that when the signal is emitted, the slot receives it
  • Slide 26
  • 26 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Qt Tutorial A set of 14 example QT tutorials can all be found online here: http://doc.qt.digia.com/4.3/tutorial.htmlhttp://doc.qt.digia.com/4.3/tutorial.html or http://web.njit.edu/all_topics/Prog_Lang_Docs/html/qt/tutorial.html Official? Qt Page http://doc.qt.digia.com/stable/http://doc.qt.digia.com/stable/ http://qt-project.org/doc/qt-4.8/http://qt-project.org/doc/qt-4.8/ Other resources http://www.zetcode.com/gui/qt4/http://www.zetcode.com/gui/qt4/
  • Slide 27
  • 27 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved NEXT PART
  • Slide 28
  • 28 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Download the Code $ mkdir lec_ttt $ cd lec_ttt $ wget http://ee.usc.edu/~redekopp/cs102/ttt_qt.tarhttp://ee.usc.edu/~redekopp/cs102/ttt_qt.tar $ tar xvf ttt_qt.tar Look up instructions on the 3 steps from our previous Qt lecture to setup and build/compile the project
  • Slide 29
  • 29 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Overall structure TTTButton models a single square in the grid and contains its type: Blank, Circle, Cross TTTBoard models the NxN tic-tac-toe grid TTT models the other controls of the game and UI
  • Slide 30
  • 30 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved TTTButton Is a derived PushButton TTTButton models a single square in the grid and contains its type: Blank, Circle, Cross setType() calls repaint() Repaint() triggers paintEvent() which TTTButton overrides Examine TTTButton::paintEvent() What if we don't call the base class version or change the ordering?
  • Slide 31
  • 31 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Q_OBJECT macro Helps Qt preprocessor define the.moc files (meta-objects) If your class derives from a Qt widget/other GUI control or uses signals and slots you should place it in the definition Declare on a line (w/o a semicolon to follow)
  • Slide 32
  • 32 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved TTTBoard Is derived from QWidget (because it contains other widgets, receives user input, and needs to be drawn/painted) Stores the TTT buttons and implements the move AI and win/lose/draw logic Examine GridLayout component which controls the display of the tic-tac- toe grid finished() signal (no definition) Signals have no definitions in a.cpp file Notice the emit statement in Connecting the clicks on buttons via buttonClicked Notice the many-to-one relationship of TTT_Button::clicked() to TTT_Board::buttonClicked() Look at buttonClicked() how do we determine which button was actually clicked? updateButtons Notice setEnabled() callWhat does that do?
  • Slide 33
  • 33 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved TTT Models the overall UI and main window Is derived from QWidget (because it contains other widgets, receives user input, and needs to be drawn/painted) QVBoxLayout Each widgeth is added via addWidget and gets slotted vertically QLabel: On screen text QComboBox Items have an ID and a display string usually Selected value from the user can be obtained with currentIndex() QPushButton Notice we connect the signals and slots (some from TTT_Board, others from ourselves (i.e. TTT) ) newState() controls the string printed on the status label
  • Slide 34
  • 34 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved main Instantiates a TTT widget and shows it (then enters the execution loop).
  • Slide 35
  • 35 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Graphics Example Go to your Qt examples directory $ mkdir ex11 $ cd ex11 $ wget http://ee.usc.edu/~redekopp/cs102/ex11.tarhttp://ee.usc.edu/~redekopp/cs102/ex11.tar $ tar xvf ex11.tar $ qmake project $ qmake $ make $./ex11 Examine the code and walkthrough at the URL below http://doc.qt.digia.com/4.3/tutorial-t11.htmlhttp://doc.qt.digia.com/4.3/tutorial-t11.html
  • Slide 36
  • 36 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved
  • Slide 37
  • 37 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved GUI Applications Are quite different from command-line applications Users have far more control over what happens next Our code must be ready to handle what the user wants to do next Execute a menu Button gets clicked Text typed into a text field And so on This makes GUI applications Event Based An event is started by something with the hardware: keyboard, mouse, etc. And complex in how things are laid out. We have menus, buttons, text fields, lists, combo boxes, etc.
  • Slide 38
  • 38 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved GUI and Qt To ease the pain of laying out a nice looking GUI, Qt has a very handy class called QMainWindow. It contains: A place for menus A tool bar A status bar 5 locations for more complex widgets
  • Slide 39
  • 39 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QMainWindow Layout
  • Slide 40
  • 40 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved MenuBar in QMainWindow A QMenuBar already exists in QMainWindow. You dont make one. To get a reference to it (from a class that inherits QMainWindow, just call the menuBar() method. QMenuBar *mb = menuBar(); You add QMenu objects to the menu bar. They are laid out from left to right. You add QAction objects to menus. They are laid out from top to bottom. You use the connect() method to connect a QAction to a method to handle the action for when the menu item is clicked on with the mouse.
  • Slide 41 addMenu(fileMenu); QAction *exitAction = new QAction( "Exit", this ); fileMenu->addAction( exitAction ); connect(exitAction, SIGNAL(triggered()), this, SLOT(exitFunction()));">
  • 41 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Setting Up Menus The code below gets the QMenuBar object from a class that inherits from QMainWindow It creates one menu a file menu It adds one action to that menu an exit action It connect the exit action to the slot function exitFunction(). We must implement this function. For each action in a menu, you repeat the last 3 lines. QMenuBar *mb = menuBar(); fileMenu = new QMenu("File, this); mb->addMenu(fileMenu); QAction *exitAction = new QAction( "Exit", this ); fileMenu->addAction( exitAction ); connect(exitAction, SIGNAL(triggered()), this, SLOT(exitFunction()));
  • Slide 42
  • 42 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Toolbars with QMainWindow Unlike the menu bar section of a QMainWindow, Qt does not automatically make a QToolBar object. Tool bars are essentially a place for a set of buttons They are laid out horizontally. Because tool bars are meant to be a place for buttons, you dont have to create button objects. You create QAction objects directly and add them to the toolbar. Its like the menu bar, but you dont have to make QMenu objects.
  • Slide 43
  • 43 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Good GUI Program Organization Up to 80% of code in a GUI program is just for creation of GUI objects, laying them out, and getting them displayed so they look nice. For each UI component, you must create it, add it to a layout, possibly add an action, and connect the action to a method. Thats up to 4 lines of code for a single UI component like a button. In addition, different parts of our application screen need to be laid out differently some horizontally, some vertically, etc.
  • Slide 44
  • 44 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Good GUI Program Organization The best way to build any GUI application, is to have each different part of the UI window be a separate class. Each class has its own layout, it also handles any signals/slots that it contains. It has a pointer to the class that created it so it can pass responsibility for some tasks to the boss class.
  • Slide 45
  • 45 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Proper Toolbar with Qt Create a new class that inherits from QToolBar Put your actions in this class Put the connect statements for each action in this class Put the methods for each connect statement in this class For PA4, you need 3 buttons start game, quit game, run A*. That can be 3 QAction objects with 3 connect statements, and 3 methods for handling the actions.
  • Slide 46
  • 46 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QToolBar with QMainWindow In the class that inherits from QToolBar Create one QAction object for each button Add each QAction to this class with addAction Have one connect statement for each QAction QAction *startGameAction = new QAction( "Start Game", this ); addAction( startGameAction ); connect( startGameAction, SIGNAL( triggered() ), this, SLOT( startGame() )));
  • Slide 47
  • 47 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Getting Started on PA4 If you havent started. Start with the code we gave you for lab 9. Change MainWindow class to another class name. Have it inherit from QGraphicsView, not QWidget Create a new MainWindow class that inherits from QMainWindow Create an instance of your QGraphicsView class in the MainWindow constructor and put it into the Central Widget with the setCentralWidget method Compile and run your code. You should see the bouncing rectangle in the middle of the window. You may have to resize the window to see it.
  • Slide 48
  • 48 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 Step 3 Create a new class that inherits from QToolBar Create the 3 actions that you need and connect each of them to a method to handle the action
  • Slide 49
  • 49 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QMainWindow Central Widget This is to be the main screen in a Qt GUI application For PA4, this is going to be your graphics window, where your puzzle game will be displayed and users will play it.
  • Slide 50
  • 50 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QDockWidgets In the QMainWindow layout scheme, there are 4 areas that immediately surround the Central Widget area. These are QDockWidgets. QDockWidgets must be assigned to one of the four locations Qt::TopDockWidgetArea, Qt::BottomDockWidgetArea, Qt::LeftDockWidgetArea, Qt::RightDockWidgetArea QDockWidgets have their own layout, that you cannot change. You must create a separate class that inherits from QWidget that you add to a QDockWidget object to be able to lay out your UI components in the way you want.
  • Slide 51
  • 51 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 Example - QLineEdits In PA4, you must have three text fields to replace the three command line arguments from PA3. The QLineEdit class is handy for single-line user input. QLineEdit text fields need a prompt to tell the user what the text field is for. You cannot assume the user knows what a given text field is for Qt provides a very nice layout for QLineEdit objects - QFormLayout
  • Slide 52
  • 52 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Using QFormLayout Like any other screen you will want to create a new class that inherits from QWidget In the constructor, create a QFormLayout object (it needs to be an instance variable of the class) Create each of the QLineEdit objects For each row you use the addRow method of the layout
  • Slide 53 addRow( Starting Moves:"), startMovesEdit ); layout->addRow( Random Seed Value:"), randomSeedEdit );">
  • 53 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Show me the Code! layout = new QFormLayout(); setLayout( layout ); sizeEdit = new QLineEdit(); startMovesEdit = new QLineEdit(); randomSeedEdit = new QLineEdit(); layout->addRow( Board Size:", sizeEdit ); layout->addRow( Starting Moves:"), startMovesEdit ); layout->addRow( Random Seed Value:"), randomSeedEdit );
  • Slide 54
  • 54 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Adding my QWidget to the Dock The last step is to create an instance of our new class and add it to the QDockWidget that we want. In the example below, this variable is uiWindow. We do this in our class that inherits from QMainWindow The setFeatures method turns off the users ability to close our dock widget, or make it a separate window. QDockWidget *qdw = new QDockWidget(); qdw->setWidget( uiWindow ); addDockWidget(Qt::LeftDockWidgetArea, qdw ); qdw->setFeatures(QDockWidget::NoDockWidgetFeatures);
  • Slide 55
  • 55 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 Step 1 From Lab 9 Rename MainWindow from Lab 9 to a new class that inherits from QGraphicsView instead of QWidget. Do not create a QGraphicsView in this class since it is one. Create an instance of this class in your new MainWindow class that inherits from QMainWindow Add this graphic window object to the Central Widget area in your new MainWindow class with the setCentralWidget method
  • Slide 56
  • 56 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 Step 2 Replace the bouncing rectangle code in your graphic window class with code to create a solved puzzle Dont worry about a 9-tile, or a 16-tile puzzle, yet. Just ensure you can create a puzzle and have it displayed in the central widget Integrate the code to scramble the puzzle from PA3. This requires moving the tiles to the proper locations Compile and run the code. Make sure you graphically moved the tiles correctly. Now you are ready to add the mousePressEvent method to your GUITile class so that the user can play the game using the mouse
  • Slide 57
  • 57 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 Step 2 Continued The mousePressEvent method is in your GUITile class. The GUITile class knows only about a single GUITile It doesnt know if a tile can be moved, or not The responsibility for knowing if a move is valid is in your graphic window class This means the GUITile class must pass the responsibility for handling a mouse click, on a GUITile, to the graphic window class
  • Slide 58
  • 58 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 Step 2 Continued For the mousePressEvent method in the GUITile class to call a method of the graphic window class, it must have a reference to that class Pass the reference to graphic window to the constructor of GUITile Create an instance variable pointer in GUITile to the graphic window object. Set the variable in the GUITile constructor
  • Slide 59
  • 59 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Show me the Code! Lets say my graphic window class is called GraphicWindow. My variable in GUITile is called gWindow In this class, I have a method moveTile that knows how/when to move a tile. This must be called from the mousePressEvent method in GUITile to get a tile moved, or not. void GUITile::mousePressEvent ( QGraphicsSceneMouseEvent* event ) { gWindow->moveTile( this ); }
  • Slide 60
  • 60 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 And Beyond Create one class at a time for some of the UI components. Compile and test each class as you create them. Consider the following class organization: One class for the 3 QLineEdit objects use QFormLayout One class for the QToolBar the 3 buttons you need One class for the 2 QRadioButton objects use QHBoxLayout, or QVBoxLayout, depending on which dock widget you use One class for the QListWidget (holds A* results)
  • Slide 61
  • 61 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved OTHER NOTES
  • Slide 62
  • 62 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Layouts We've seen different layouts QVBoxLayout QHBoxLayout QFormLayout Each widget (or derived class) can have only one Layout Set by calling: widget->setLayout(pointer to the layout) method But a layout may contain either widgets or OTHER LAYOUTS in each of its entries Set by calling: layout->addLayout(pointer to child layout) Set by calling: layout->addWidget(pointer to the child widget) So for each widget think about whether you want to add items vertically or horizontally and pick a Vbox or Hbox Layout and then add child layouts within that context
  • Slide 63
  • 63 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved More Notes Widgets have a virtual function sizeHint() Qsize sizeHint() const; If you want your widget to start at a particular size, add this to your class and simply have it return a Qsize object which is just pixel rows x columns Qsize MYCLASS::sizeHint() const { return QSize(400, 400); } Defining your own signals Signals go in the "signals:" section of your class They are just prototypes (you don't write an implementation) Use the 'emit' keyword followed by a "call" to this signal function Whatever slot has been connected to this signal will in turn be called Events are not slots (think of them as "slots" that are pre- connected to certain actions/signals) Just override them and usually call the BaseClass version
  • Slide 64
  • 64 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved
  • Slide 65
  • 65 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA 5 PA 5 is the first of two assignments for creating a game in Qt You are to have 5 types of things in your game. One does not have to move (walls, buildings, etc.) The movement behaviors MUST be different. Just moving faster/slower is not different. To play your game, you can use the mouse, or the keyboard, or both. It is your choice. It is your game! Each of your 5 things are to be displayed with images. No rectangles, ellipses, etc. You are to have menus for starting a game, pausing a game, stopping a game, and quitting the program. You are to have a score for the player, and health/lives.
  • Slide 66
  • 66 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Images in Qt A convenient class for images is QGraphicsPixmapItem Key: Loading an image, initially, from a file is SSSSLLLLOOOOWWW!!!! You only want to read an image file once! Displaying an image in a scene is separate from reading the image file. You can display the same image file in multiple locations. QPixmap is the class for reading an image file QGraphicsPixmapItem objects can be created and passed a QPixmap object. This is what you will display. QPixmap: Reads an imageDo this once QGraphicsPixmapItem: Create as many as you want passing a pointer to the QPixMap to each
  • Slide 67
  • 67 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved QGraphicsPixmapItem You add these to your scene just like QGraphicsRectItem and QGraphicsSimpleTextItem addItem method You move them just like QGraphicsSimpleTextItem setPos method providing the x and y coordinates of the upper left corner They contain a QPixmap object inside of them You can assign a QPixmap object to a QGraphicsPixmapItem object through the setPixmap method
  • Slide 68
  • 68 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved POLYMORPHISM & INHERITANCE Tracking Items
  • Slide 69
  • 69 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Heres a possible game There are 3 different things shown Some overlap they have collided Do some die, or is it a good thing? How do we know they have collided? We have to keep track of EVERY thing!!!!
  • Slide 70
  • 70 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Keeping Track of Things You are to have 5 different types of things. You will want 5 different classes for your things. To keep track of them, you would need 5 different lists Finding collisions means comparing the items in one list to each of the items in the other 4 lists. Thats multiple for loops. Unless we use inheritance, virtual functions, and the benefit of polymorphism (many forms). Then we can do it with a single list!
  • Slide 71
  • 71 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Create an Abstract Superclass class Thing: public QGraphicsPixmapItem { public: Thing (QPixmap *pm, int nx, int ny); virtual void move() = 0; //virtual function. Class Thing is abstract. For a reason. private: //Every thing has a origin and a velocity maybe 0 int x; int y; int vX; int vY; QPixmap *pixMap; //Good idea. Explain later. }; //Every thing needs this. You may want even more inherited here
  • Slide 72
  • 72 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Thing Superclass Constructor Thing::Thing( QPixmap* p, int nx, int ny ) { pixMap = p; //Handy to store separate to get image width/height, etc. setPixmap( *p ); //First Qt method that doesnt take a pointer :-> x = nx; y = ny; setPos( x, y ); //how you set the position }
  • Slide 73
  • 73 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Create a Subclass from Thing class BigThing: public Thing { public: BigThing (QPixmap *pm, int nx, int ny); void move(); // Implement the move method }; BigThing::BigThing( QPixmap *pm, int nx, int ny ) : Thing( pm, nx, ny ) { //Any specific initialization code for BigThing goes here. } void BigThing::move() { //Implement the movement behavior of BigThing here. This is required. } //You may need other methods
  • Slide 74
  • 74 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Create Another Subclass class SmallThing: public Thing { public: SmallThing (QPixmap *pm, int nx, int ny); void move(); // Implement the move method }; SmallThing::AmallThing( QPixmap *pm, int nx, int ny ) : Thing( pm, nx, ny ) { //Any specific initialization code for SmallThing goes here. } void SmallThing::move() { //Implement the movement behavior of SmallThing here. This is required. } //You may need other methods
  • Slide 75
  • 75 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved So what? BigThing and SmallThing are both Things. Yes? That means that we can have a single list that contains both BigThings and SmallThings. Or can we? How about his code? Vector myThings; BigThing* b = new BigThing(); // Lets pretend a default constructor myThing.push_back( b ); SmallThing* s = new SmallThing(); myThing.push_back( s); for ( int i=0; i
  • 82 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved More code void MainWindow::keyPressEvent( QKeyEvent *e ) { //We need to find out which key was pressed //Lets say we want to use the 4 arrow keys switch ( e->key() ) { case Qt::Key_Left : //Left arrow pushed do the work case Qt::Key_Right : //Right arrow pushed case Qt::Key_Up : //Up arrow pushed case Qt::Key_Down //Down arrow pushed } //There are codes for all possible keys in Qt
  • Slide 83
  • 83 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Last Keyboard Focus Issue When Qt starts up, nothing has focus. Interesting, that alphanumeric keys work, but arrow keys do not, if you do not set an initial focus In your main window class (e.g. QMainWindow inheriting class) you MUST add one more statement to your constructor: setFocus() This will ensure the non-alphanumeric keys will work as soon as your program starts.
  • Slide 84
  • 84 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved WHEN ITEMS COLLIDE How to detect collision of QGraphicsItems
  • Slide 85
  • 85 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Collisions Matter You may have: Good things hit bad things Good things hit good things help life, etc. Bad things hurt/help bad things It all comes down to collisions How to know when a thing collides with a thing? Simple: collidesWithItem() method Whats the algorithm? It depends. Is it all the bad things against the player? Or can a bad thing take away a good thing, so that the player cannot get it? Worst case. Any thing can interact with any other thing Thats O(n 2 ) Best case. Its the player against the bad guy world
  • Slide 86
  • 86 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved Worst Case Collisions Any thing can interact with any other thing for ( int i=0; i< things.size(); i++ ) { Thing* itemA = myThings[i]; for ( int j=0; j< things.size(); j++ ) { Thing* itemB = myThings[j]; if ( i == j ) { continue; //I can always collide with myself } if ( itemA.collidesWithItem( itemB) ) { //There is a collision. Handle it. }
  • Slide 87
  • 87 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved You Against the World If your game is the player against all the bad things You dont need a double for loop. You will compare the player against the list of things A single for loop is all you need.
  • Slide 88
  • 88 Copyright 2013 Brent Nash & Mark Redekopp, All Rights Reserved PA4 versus PA 5 If you created a GraphicWindow class and put it in your central widget window in PA4, you are in good shape for PA5. All you need to do is change your GraphicWindow class to be your game You will need to change your dock widgets (or other control widgets), but that is a separate task from changing your GraphicWindow class