0

In my project, I have 256 tiny PushButtons in one 16x16 grid layout. (Yeah that took forever.) Editing and running my program now is very laggy. Also, for some strange reason, Qt will not let me enable any of the buttons, but other buttons to the side work just fine?

Is there any easy way to determine which square of the grid was clicked without having a bunch of buttons? (Like following the cursor over an image maybe?)

Also, when each "square" of the grid is clicked, it becomes the "selection" and it needs to be the only "square" selected. (Think about it like a huge chess board)

Here is a pic: http://gyazo.com/988cdbb59b3d1f1873c41bf91b1408fd

Later on, I will need to do this again for a 54x54 size grid (2916 buttons) and I REALLY don't want to do it button by button.

Thanks for your time, I hope you understand my question :)

Mat
  • 202,337
  • 40
  • 393
  • 406
mrg95
  • 2,371
  • 11
  • 46
  • 89
  • Please show the relevant code. Also: QGraphicsView could be more appropriate in some circumstances. – Mat Aug 20 '13 at 05:35
  • There is no relevant code. Just read my question. It's not a coding problem. – mrg95 Aug 20 '13 at 05:36
  • 1
    You've got stuff that "lags horribly" and you only provide an image. How are we supposed to help you with that? "I really don't want to do it button by button" raises doubts about the structure of your existing code. "Is there an easy way [...]?" yes, the maths are pretty simple but that's not the right solution - the solution is to fix whatever it is that's causing lag (or using a different technique, i.e. QGraphicsView _could_ be better, but not telling without knowing the details of what you're currently doing.) – Mat Aug 20 '13 at 05:40
  • Seriously? Do I need to upload a video of lag for you? Using the other features in my program and editing it in QtDesigner mode is laggy. Button by button means I placed, resized, ordered, named, and moved each button one at a time. I have so many buttons, my program is laggy. I am looking for a simpler alternative to making a huge grid of buttons. – mrg95 Aug 20 '13 at 05:43
  • No, I want to see code. I don't care about pictures, videos or a description of code - none of those tell me exactly what you're doing. If you're laying out such a grid with Qt Designer, that's probably the start of your problem - must look pretty ugly. – Mat Aug 20 '13 at 05:45
  • What is wrong with using Qt Designer? It doesn't look "ugly" it looks exactly how I want it to. What "code" do you want me to show you. I didn't write any code, I just placed down a lot of buttons, which is beside the point. I'M LOOKING FOR AN ALTERNATIVE. Basically, a "what would you do" type of question.... – mrg95 Aug 20 '13 at 05:48
  • 1
    I'm talking about **the code** that must look ugly unless Qt Designer allows you to define a proper array or grid of buttons that is held in a proper collection type and not one 100 different independent variables in your UI class. I already offered you on alternative. The second is to code that widget yourself with a sane structure for the buttons. – Mat Aug 20 '13 at 05:50
  • I'm confused. Wouldn't it still lag though? Because it is still just a bunch of buttons? – mrg95 Aug 20 '13 at 05:54
  • Look, I have no idea - how could I, I have no idea what code you're running, or how it is wired up. – Mat Aug 20 '13 at 06:02
  • A better way to create the grid would be to do it programatically. It might take a bit longer to get the layout looking absolutely perfect but it will allow you to quickly switch to any size grid you wish by just changing some function parameters. – RobbieE Aug 20 '13 at 06:40
  • QGraphicsView seems to be what you need. I'm not exactly sure what you're doing though. It seems to me that you have some sort of image that you want to divide in a grid and detect which cell was clicked. – thuga Aug 20 '13 at 07:11
  • What are you trying to do? I'm not sure your current implementation (just dragging thousands of buttons in a grid to detect what position is clicked?) is the simplest method to do what you're looking for. Almost every single object (Qwidget based) can have a mousePressEvent which can return where the mouse currently is located which would allow you to get the mouse click location without using so many buttons – g19fanatic Aug 20 '13 at 16:42

3 Answers3

1

You can do this easy way.

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import * 

class DrawImage(QMainWindow): 
    def __init__(self, parent=None):
        super(QMainWindow, self).__init__(parent)
        self.setWindowTitle('Select Window')
        
        #you can set grid size here ... 8x8, 16x16 , for bigger numbers (54x54) be sure your image is big enough, because QWidget can't be smaller then ~20 pixels
        self.gridSize = 16

        mainWidget = QWidget()
        self.setCentralWidget(mainWidget)
        self.scene = QGraphicsScene()
        view = QGraphicsView(self.scene)
        layout = QVBoxLayout()
        layout.addWidget(view)
        mainWidget.setLayout(layout)
        self.image = QImage('image.JPG')# put your image name here, image (suppose to be grid) must be at the same folder or put full path
        pixmapItem = QGraphicsPixmapItem(QPixmap(self.image), None, self.scene)
        pixmapItem.mousePressEvent = self.pixelSelect
        

    def pixelSelect( self, event ):
        #add whatever you want to this widget,any functionality or you can add image for example, I've simply colored it
        wdg = QWidget()
        layout = QVBoxLayout()
        palette =  QPalette(wdg.palette())
        palette.setBrush(QPalette.Background, QColor(200,255,255))
        wdg.setPalette(palette)
        wdg.setLayout(layout)
        self.scene.addWidget(wdg)
        
        #calculate size and position for added widget
        imageSize = self.image.size()
        width = imageSize.width()
        height = imageSize.height() 

        #size
        wgWidth = float(width)/self.gridSize  
        wgHeight =  float(height)/self.gridSize
        wdg.setFixedSize(wgWidth,wgHeight)

        #position       
        wgXpos = int(event.pos().x()/wgWidth) * wgWidth
        wgYpos = int(event.pos().y()/wgHeight) * wgHeight
        wdg.move(wgXpos,  wgYpos)

        #which square is clicked?
        print "square at row ", int(event.pos().y()/wgHeight)+1,", column ",int(event.pos().x()/wgWidth)+1, "is clicked"

def main():
    app = QtGui.QApplication(sys.argv)
    form = DrawImage()
    form.show()
    app.exec_()

if __name__ == '__main__':
    main()

Also, if you want to display simple square image over your grid image, look at question/solution I had: QGraphicsPixmapItem won't show over the other QGraphicsPixmapItem

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Aleksandar
  • 3,541
  • 4
  • 34
  • 57
  • I'm using c++. I put that in the title, but the darn moderators always take it out. Drives me insane – mrg95 Sep 04 '13 at 07:04
  • Oh, sorry, I didn't see that. Anyway, you can get an idea from a given Python code (and from code in the given link) and translate it to C++. If you want to try Python code: I am using Python2.6 , PyQt4.7, eclipse with PyDev. Good luck. – Aleksandar Sep 04 '13 at 08:25
1

If you don't really need the appearance of buttons, I would create a QWidget subclass that implements a custom paintEvent and renders a grid of needed size (taking the widget size into account). Then, in the mouse events (up,down,move etc.) you can calculate which grid item was clicked with a simple formula. You can render cells with different colors to indicate selection or highlighting.

P.S.:I would really like to post some code from my implementations (i have done this two or three times) but the source codes are at my old company :)

erelender
  • 6,175
  • 32
  • 49
0

You just create your own QGridLayout in order to be able to add the buttons easily. I posted an answer to another question, showing you how to fill a custom made QGridLayout with a bunch of widgets sequentially. The buttons are added according to the maximum count of columns you specified. (Note: It's just a very rough example but enough to start from)

In your example you would create the custom grid layout with 16 columns and simply add your buttons.

To find out which button has been pressed (and to make connecting easier) you can use QSignalMapper.

For investigating the lag you could check the amount of (GDI-/User-) handles of your application (using ProcessExplorer for example). The handle count shouldn't be above 10.000.

I don't know why you can't enable the push buttons.

Community
  • 1
  • 1
Exa
  • 4,020
  • 7
  • 43
  • 60