#!/usr/bin/env ruby -w # # A class that lets the user draw with the mouse. The # window knows how to redraw itself. # retquire 'Qt' class ScribbleArea < TQt::Widget slots "setColor(TQColor)", "slotLoad(const TQString&)", "slotSave(const TQString&)", "slotClearArea()" # # The constructor. Initializes the member variables. # def initialize() super # initialize member variables @_buffer = TQt::Pixmap.new() @_last = TQt::Point.new() @_currentcolor = black # don't blank the window before repainting setBackgroundMode( NoBackground ) # create a pop-up menu @_popupmenu = TQt::PopupMenu.new() @_popupmenu.insertItem( "&Clear", self, SLOT( "slotClearArea()" ) ) end # # This slot sets the curren color for the scribble area. It will be # connected with the colorChanged( TQt::Color ) signal from the # ScribbleWindow. # def setColor( new_color ) @_currentcolor = new_color end # # This slot clears the drawing area by filling the off-screen buffer with # white and copying it over to the window. # def slotClearArea() # fill the off screen buffer with plain white @_buffer.fill( white ) # and copy it over to the window bitBlt( self, 0, 0, @_buffer ) end # # This method does the actual loading. It relies on TQt::Pixmap (and the # underlying I/O machinery) to determine the filetype. # def slotLoad( filename ) if !@_buffer.load( filename ) TQt::MessageBox.warning( nil, "Load error", "Could not load file" ) end repaint() # refresh the window end # # This method does the actual saving. We hard-code the file type as # BMP. Unix users might want to replace this with something like XPM. # def slotSave( filename ) if !@_buffer.save( filename, "BMP" ) TQt::MessageBox.warning( nil, "Save error", "Could not save file" ) end end # # This method is called whenever the user presses the # mouse over the window. It just records the position of the mouse # at the time of the click. # def mousePressEvent(event) if event.button() == RightButton @_popupmenu.exec( TQt::Cursor.pos() ) else @_last = event.pos() # retrieve the coordinates from the event end end # # The method is called whenever the usr moves the mouse # while the mouse button is pressed. If we had called # setMouseTracking(true) before, the method would also be called # when the mouse was moved with any button pressed. We know that # we haven't, and thus don't have to check whether any buttons are # pressed. # def mouseMoveEvent(event) # create a TQt::Painter object for drawing onto the window windowpainter = TQt::Painter.new() # and another TQt::Painter object for drawing int an off-screen pixmap bufferpainter = TQt::Painter.new() # start painting windowpainter.begin( self ) # This painter paints onto the window bufferpainter.begin( @_buffer ) # and this one paints in the buffer # set a standard pen with the currently selected color windowpainter.setPen( @_currentcolor ) bufferpainter.setPen( @_currentcolor ) # draw a line in both the window and the buffer windowpainter.drawLine( @_last, event.pos() ) bufferpainter.drawLine( @_last, event.pos() ) # done with painting windowpainter.end() bufferpainter.end() # remember the current mouse position @_last = event.pos() end # # This method is called whenever the widget needs # painting, for example when it has been obscured and then revealed again. # def paintEvent(event) bitBlt(self, 0, 0, @_buffer) end # # This method get called whenever the widget needs # painting, for example, when it has been obscured and then revealed again. # def resizeEvent(event) save = TQt::Pixmap.new( @_buffer ) @_buffer.resize( event.size() ) @_buffer.fill( white ) bitBlt( @_buffer, 0, 0, save ) end end class ScribbleWindow < TQt::Widget slots "slotAbout()", "slotAboutQt()", "slotColorMenu(int)", "slotLoad()", "slotSave()" signals "colorChanged(TQColor)", "load(const TQString&)", "save(const TQString&)" COLOR_MENU_ID_BLACK = 0 COLOR_MENU_ID_RED = 1 COLOR_MENU_ID_BLUE = 2 COLOR_MENU_ID_GREEN = 3 COLOR_MENU_ID_YELLOW = 4 def initialize() super # The next lines build the menu bar. We first create the menus # one by one, then add them to the menu bar. # @_filemenu = TQt::PopupMenu.new() # create a file menu @_filemenu.insertItem( "&Load", self, SLOT( "slotLoad()" ) ) @_filemenu.insertItem( "&Save", self, SLOT( "slotSave()" ) ) @_filemenu.insertSeparator() @_filemenu.insertItem( "&Quit", $qApp, SLOT( "quit()" ) ) @_colormenu = TQt::PopupMenu.new() # create a color menu @_colormenu.insertItem( "B&lack", COLOR_MENU_ID_BLACK) @_colormenu.insertItem( "&Red", COLOR_MENU_ID_RED) @_colormenu.insertItem( "&Blue", COLOR_MENU_ID_BLUE) @_colormenu.insertItem( "&Green", COLOR_MENU_ID_GREEN) @_colormenu.insertItem( "&Yellow", COLOR_MENU_ID_YELLOW) TQt::Object.connect( @_colormenu, SIGNAL( "activated( int )" ), self, SLOT( "slotColorMenu( int )" ) ) @_helpmenu = TQt::PopupMenu.new() # create a help menu @_helpmenu.insertItem( "&About QtScribble", self, SLOT( "slotAbout()" ) ) @_helpmenu.insertItem( "&About Qt", self, SLOT( "slotAboutQt()" ) ) @_menubar = TQt::MenuBar.new( self, "" ) # create a menu bar @_menubar.insertItem( "&File", @_filemenu ) @_menubar.insertItem( "&Color", @_colormenu ) @_menubar.insertItem( "&Help", @_helpmenu ) # We create a TQt::ScrollView and a ScribbleArea. The ScribbleArea will # be managed by the scroll view.# @_scrollview = TQt::ScrollView.new( self ) @_scrollview.setGeometry( 0, @_menubar.height(), width(), height() - @_menubar.height() ) @_scribblearea = ScribbleArea.new() @_scribblearea.setGeometry( 0, 0, 1000, 1000 ) @_scrollview.addChild( @_scribblearea ) TQt::Object.connect( self, SIGNAL( "colorChanged(TQColor)" ), @_scribblearea, SLOT( "setColor(TQColor)" ) ) TQt::Object.connect( self, SIGNAL( "save(const TQString&)" ), @_scribblearea, SLOT( "slotSave(const TQString&)" ) ) TQt::Object.connect( self, SIGNAL( "load(const TQString&)" ), @_scribblearea, SLOT( "slotLoad(const TQString&)" ) ) end def resizeEvent( event ) # When the whole window is resized, we have to rearrange the geometry # in the ScribbleWindow as well. Note that the ScribbleArea does not need # to be changed. @_scrollview.setGeometry( 0, @_menubar.height(), width(), height() - @_menubar.height() ) end def slotAbout() TQt::MessageBox.information( self, "About QtScribble 5", "This is the Scribble 5 application\n" + "Copyright 1998 by Mathias Kalle Dalheimer\n") end def slotAboutQt() TQt::MessageBox.aboutTQt( self, "About Qt" ) end def slotColorMenu( item ) case item when COLOR_MENU_ID_BLACK emit colorChanged( black ) when COLOR_MENU_ID_RED emit colorChanged( darkRed ) when COLOR_MENU_ID_BLUE emit colorChanged( darkBlue ) when COLOR_MENU_ID_GREEN emit colorChanged( darkGreen ) when COLOR_MENU_ID_YELLOW emit colorChanged( yellow ) end end # # This is the slot for the menu item File/Load. It opens a # TQt::FileDialog to ask the user for a filename, then emits a save() # signal with the filename as parameter. # def slotLoad() # Open a file dialog for loading. The default directory is the # current directory, the filter *.bmp. # filename = TQt::FileDialog.getOpenFileName( ".", "*.bmp", self ) if !filename.nil? emit load( filename ) end end # # This is the slot for the menu item File/Load. It opens a # TQt::FileDialog to ask the user for a filename, then emits a save() # signal with the filename as parameter. # def slotSave() # Open a file dialog for saving. The default directory is the # current directory, the filter *.bmp. # filename = TQt::FileDialog.getSaveFileName( ".", "*.bmp", self ) if !filename.nil? emit save( filename ) end end end myapp = TQt::Application.new(ARGV) mywidget = ScribbleWindow.new() mywidget.setGeometry(50, 500, 400, 400) myapp.setMainWidget(mywidget) mywidget.show() myapp.exec()