wxBufferedPaintDC (Контекст устройства) Проблема с обработчиком события wxPython onPaint - PullRequest
1 голос
/ 08 июня 2011

У меня есть класс с именем imageBrowser, который отображает изображение в wxMDIChildFrame.Этот класс в основном предназначен для отображения изображения пользователю с набором элементов управления для просмотра набора изображений.Теперь в этом классе я переопределил обработчик событий onPaint, чтобы ответить на элементы управления, прикрепленные к этому wxMDIChildFrame.Таким образом, на imageBrowser есть два флажка: один для наложения сетки, а другой для наложения шкалы.Если этот флажок установлен, DC рисует сетку поверх изображения или масштабную линейку.Эти методы работают нормально.Проблема возникает, когда я отмечаю другой флажок в отдельном wxMDIChildFrame, чтобы нарисовать несколько случайных точек на изображении, сетка и масштабная шкала исчезают сразу после установки этого флажка.Однако, если я просто изменим размер imageBrowser, wxMDIChildFrame, появится сетка, масштабная линейка и точки.Итак, вот мой обработчик onPaint:

def OnPaint(self, event):
    dc = wx.BufferedPaintDC(self.staticBitmap, self.staticBitmap.GetBitmap())
    dc.Clear()
    dc.DrawBitmap(self.wxBitmap, 0, 0)
    self.drawScaleBar(dc)
    self.drawGrid(dc)
    self.drawDots(dc)
    event.Skip()

def drawGrid(self, dc):
    gridWid, gridHgt = self.staticBitmap.GetBitmap().GetSize()
    numRows, numCols = self.gridSize, self.gridSize
    if self.controlPanel.showGridBox.IsChecked():
        dc.SetPen(wx.Pen(self.gridColor, self.gridThickness))
        dc.SetTextForeground(self.gridColor)
        cellWid = float( gridWid - 1) / numRows
        cellHgt = float( gridHgt - 1) / numCols
        for rowNum in xrange( numRows + 1) :
            dc.DrawLine( 0, rowNum*cellHgt, gridWid, rowNum*cellHgt )
        for colNum in xrange( numCols + 1 ) :
            dc.DrawLine( colNum*cellWid, 0, colNum*cellWid, gridHgt )


def drawScaleBar(self, dc):
    gridWid, gridHgt = self.wxBitmap.GetSize()
    if self.controlPanel.showScaleBar.IsChecked():
        dc.SetPen(wx.Pen(self.scaleColor, 2))
        dc.SetTextForeground(self.scaleColor)
        width = self.Tools.imageInfo.size.GetLabel().split()[1]
        #Scales the bar to the image width.  If the user selected scale is larger than
        #the current image the scale is set to the maximum width of the image.
        if width != 'None':
            width = width.replace('m', '')
            width = float(width)
            lineSize = ((gridWid/width) * (self.scaleSize/100.0))
            if lineSize > gridWid:
                lineSize = (gridWid * 0.9) - 1
                self.scaleSize = int(width * 100 - 10)
                self.controlPanel.chooseScaleSize.SetValue(str(self.scaleSize))
                self.drawScaleBar(dc)
            elif self.scaleLoc == 'Top Left':
                dc.DrawLine(10, gridHgt * 0.1, 10 + lineSize, gridHgt * 0.1)
                dc.DrawLine(10, gridHgt * 0.1 + 10, 10, gridHgt * 0.1 - 10)
                dc.DrawLine(10 + lineSize, gridHgt * 0.1 + 10, 10 + lineSize, gridHgt * 0.1 - 10)
                dc.DrawText(str(self.scaleSize) + 'cm', (10 + 10 + lineSize)/2.0 - 15, gridHgt * 0.1 - 25)
            elif self.scaleLoc == 'Top Right':
                dc.DrawLine(gridWid - 10, gridHgt * 0.1, (gridWid - 10) - lineSize, gridHgt * 0.1)
                dc.DrawLine(gridWid - 10, gridHgt * 0.1 + 10, gridWid - 10, gridHgt * 0.1 - 10)
                dc.DrawLine((gridWid - 10) - lineSize, gridHgt * 0.1 + 10, (gridWid - 10) - lineSize, gridHgt * 0.1 - 10)
                dc.DrawText(str(self.scaleSize) + 'cm', ((gridWid - 10 - lineSize)+(gridWid - 10))/2.0 - 20, gridHgt * 0.1 - 25)
            elif self.scaleLoc == 'Bottom Left':
                dc.DrawLine(10, gridHgt * 0.9, 10 + lineSize, gridHgt * 0.9)
                dc.DrawLine(10, gridHgt * 0.9 + 10, 10, gridHgt * 0.9 - 10)
                dc.DrawLine(10 + lineSize, gridHgt * 0.9 + 10, 10 + lineSize, gridHgt * 0.9 - 10)
                dc.DrawText(str(self.scaleSize) + 'cm', (10 + 10 + lineSize)/2.0 - 15, gridHgt * 0.9 - 25)
            elif self.scaleLoc == 'Bottom Right':
                dc.DrawLine(gridWid - 10, gridHgt * 0.9, (gridWid - 10) - lineSize, gridHgt * 0.9)
                dc.DrawLine(gridWid - 10, gridHgt * 0.9 + 10, gridWid - 10, gridHgt * 0.9 - 10)
                dc.DrawLine((gridWid - 10) - lineSize, gridHgt * 0.9 + 10, (gridWid - 10) - lineSize, gridHgt * 0.9 - 10)
                dc.DrawText(str(self.scaleSize) + 'cm', ((gridWid - 10 - lineSize)+(gridWid - 10))/2.0 - 20, gridHgt * 0.9 - 25)
        else:
            #If there is no depth or size information for the current image the scale
            #bar is collapsed and '0cm' is displayed.
            if self.scaleLoc == 'Top Left':
                dc.DrawLine((15) + (gridWid/15), gridHgt * 0.1 + 10, (15) + (gridWid/15), gridHgt * 0.1 - 10)
                dc.DrawText('0cm', (15) + (gridWid/15/2), gridHgt * 0.1 - 25)
            elif self.scaleLoc == 'Top Right':
                dc.DrawLine((gridWid * 0.9) - (gridWid/15), gridHgt * 0.1 + 10, (gridWid * 0.9) - (gridWid/15), gridHgt * 0.1 - 10)
                dc.DrawText('0cm', (gridWid * 0.9) - (gridWid/15), gridHgt * 0.1 - 25)
            elif self.scaleLoc == 'Bottom Left':
                dc.DrawLine((15) + (gridWid/15), gridHgt * 0.9 + 10, (15) + (gridWid/15), gridHgt * 0.9 - 10)
                dc.DrawText('0cm', (15) + (gridWid/15/2), gridHgt * 0.9 - 25)
            elif self.scaleLoc == 'Bottom Right':
                dc.DrawLine((gridWid * 0.9) - (gridWid/15), gridHgt * 0.9 + 10, (gridWid * 0.9) - (gridWid/15), gridHgt * 0.9 - 10)
                dc.DrawText('0cm', (gridWid * 0.9) - (gridWid/15), gridHgt * 0.9 - 25)

def drawDots(self, dc):
    if self.Tools.classificationTool.dotEnable.GetValue():
        for dictionary in Workspace.assignmentHash:
            if dictionary.keys()[0] == Workspace.data.getImageName(Workspace.currentImageIndex):
                dc.SetPen(wx.Pen('Red', 1))
                dc.SetBrush(wx.Brush('Red'))
                print 'This image should have Dots!'
                index = Workspace.assignmentHash.index(dictionary)
                for dict in Workspace.assignmentHash[index].values()[0]:
                    s = dict.keys()[0]
                    r = re.search('(d\d+)(\(\d.\d+,\d.\d+\))', s)
                    num = r.group(1)[1:]
                    coord = r.group(2).split(',')
                    x = float(coord[0][1:])
                    x *= (Workspace.iWidth*Workspace.zoomScale)
                    x = int(x)
                    y = float(coord[1][:-1])
                    y *= (Workspace.iHeight*Workspace.zoomScale)
                    y = int(y)
                    dc.DrawCircle(x, y, 3)

Опять же, это работает нормально, если флажок для drawDots (расположенный в другом wxMDIChildFrame) не включен.Важно отметить, что этот другой wxMDIChildFrame изначально загружается как просто пустой кадр.Затем пользователь открывает «Файл классификации», который уничтожает этот начальный пустой кадр, удаляет его начальное меню из строки меню, а затем повторно инициализирует его с помощью виджетов на основе «файла классификации», а затем добавляет меню обратно в меню с дополнительнымиопции.Только после того, как этот «файл классификации» был открыт, флажок очищает сетку / шкалу.

Я реализовал метод drawDots() так же, как реализовал drawGrid() и drawScaleBar().Разница лишь в том, что флажок для drawDots() относится к другому классу.Обработчик событий для этого флажка буквально ничего не делает, за исключением вызова родительского класса, который вызывает событие перерисовки, вызывая другой метод, использующий Refresh().Это способ, которым методы drawScaleBar() и drawGrid() также делают это.

Как я могу решить эту проблему?

...