wxpython + after changing panel and redo layout panel is very small - resize

I change my panels by destroying panel 1 and then show panel 2. I cannot use the method creating both and hide en show, because than I have other problems. But after redo my layout my panel is very small. How can I make it the same size as before?
This is my testcode
import wx
class Main(wx.Frame):
def __init__(self, parent=None, id=-1, notify_channel="chanMicroanalysis", **kwargs):
# general panel information
wx.Frame.__init__(self, parent, wx.ID_ANY)
self.SetTitle('Microanalysis')
self.backpanel = wx.Panel(self, wx.ID_ANY)
# first panel
self.Choicepanel = wx.Panel(self.backpanel, wx.ID_ANY)
self.lblChoose = wx.StaticText(self.Choicepanel, label="Choose:")
self.btnChooseFilterOnly = wx.Button(self.Choicepanel, wx.ID_ANY, "Filter only ")
self.btnChooseMA = wx.Button(self.Choicepanel, wx.ID_ANY, "Microanalyse")
self.btnChooseCellInfo = wx.Button(self.Choicepanel, wx.ID_ANY, " CellInfo ")
self.btnChooseReport = wx.Button(self.Choicepanel, wx.ID_ANY, "Report")
# second panel: cellinfo
self.test1 =wx.Panel(self.backpanel, wx.ID_ANY)
self.Cellinfopanel = self.test1
self.lblChooseingo = wx.StaticText(self.Cellinfopanel, label="Choose:")
self.btnChooseFilter = wx.Button(self.Cellinfopanel, wx.ID_ANY, "Filter only ")
self.btnChooseprr = wx.Button(self.Cellinfopanel, wx.ID_ANY, "Microanalyse")
self.btnChooseCell = wx.Button(self.Cellinfopanel, wx.ID_ANY, " CellInfo ")
self.btnChoose = wx.Button(self.Cellinfopanel, wx.ID_ANY, "Report")
self._do_layout()
self._do_bindings()
def _do_layout(self):
self.h_main_sizer = wx.BoxSizer()
self.h_centerbuttonsizer = wx.BoxSizer()
self.h_centerbutton1sizer = wx.BoxSizer()
self.v_firstsizer = wx.BoxSizer(wx.VERTICAL)
self.v_secondsizer = wx.BoxSizer(wx.VERTICAL)
self.v_thirdsizer = wx.BoxSizer(wx.VERTICAL)
self.v_fourthsizer = wx.BoxSizer(wx.VERTICAL)
self.v_buttonsizer = wx.BoxSizer(wx.VERTICAL)
self.v_button1sizer = wx.BoxSizer(wx.VERTICAL)
########################################"
self.v_firstsizer.Add(self.Choicepanel, 1, wx.EXPAND)
self.v_buttonsizer.Add(self.lblChoose, 0, wx.CENTER)
self.v_buttonsizer.Add(self.btnChooseFilterOnly, 0, wx.EXPAND)
self.v_buttonsizer.Add(self.btnChooseMA, 0, wx.EXPAND)
self.v_buttonsizer.Add(self.btnChooseCellInfo, 0, wx.EXPAND)
self.v_buttonsizer.Add(self.btnChooseReport, 0, wx.EXPAND)
self.h_centerbuttonsizer.AddStretchSpacer(1)
self.h_centerbuttonsizer.Add(self.v_buttonsizer, 0, wx.CENTER)
self.h_centerbuttonsizer.AddStretchSpacer(1)
self.Choicepanel.SetSizer(self.h_centerbuttonsizer)
self.h_centerbuttonsizer.Fit(self.Choicepanel)
########################################"
self.v_secondsizer.Add(self.Cellinfopanel, 5, wx.EXPAND)
self.v_button1sizer.Add(self.lblChooseingo, 0, wx.CENTER)
self.v_button1sizer.Add(self.btnChooseFilter, 0, wx.EXPAND)
self.v_button1sizer.Add(self.btnChooseprr, 0, wx.EXPAND)
self.v_button1sizer.Add(self.btnChooseCell, 0, wx.EXPAND)
self.v_button1sizer.Add(self.btnChoose, 0, wx.EXPAND)
self.h_centerbutton1sizer.AddStretchSpacer(1)
self.h_centerbutton1sizer.Add(self.v_button1sizer, 0, wx.CENTER)
self.h_centerbutton1sizer.AddStretchSpacer(1)
self.Cellinfopanel.SetSizer(self.h_centerbutton1sizer)
self.h_centerbutton1sizer.Fit(self.Choicepanel)
########################################"
self.h_main_sizer.Add(self.v_firstsizer, 20, wx.EXPAND)
self.h_main_sizer.Add(self.v_secondsizer, 20, wx.EXPAND)
self.backpanel.SetSizer(self.h_main_sizer)
self.h_main_sizer.Fit(self)
#
# self.Choicepanel.Show()
# self.Cellinfopanel.Hide()
# self.MApanel.Hide()
# self.Reportpanel.Hide()
self.Choicepanel.Show()
self.Cellinfopanel.Show()
self.statusMAPanelShown = False
def _do_bindings(self):
self.btnChooseprr.Bind(wx.EVT_BUTTON, self.on_chooseMA)
def on_chooseMA(self, event):
print "in choose MA"
self.showMAPanel()
self._do_layout()
#
# self.Layout()
def showMAPanel(self):
print "in showmapanel"
self.test1.Destroy()
self.test2 =wx.Panel(self.backpanel, wx.ID_ANY)
self.Cellinfopanel = self.test2
self.lblChooseingo = wx.StaticText(self.Cellinfopanel, label="test:")
self.btnChooseFilter = wx.Button(self.Cellinfopanel, wx.ID_ANY, "test1 ")
self.btnChooseprr = wx.Button(self.Cellinfopanel, wx.ID_ANY, "test2")
self.btnChooseCell = wx.Button(self.Cellinfopanel, wx.ID_ANY, " test3 ")
self.btnChoose = wx.Button(self.Cellinfopanel, wx.ID_ANY, "test4")
if __name__ == '__main__':
app = wx.PySimpleApp()
MAview = Main(None, wx.ID_ANY)
MAview.Maximize()
MAview.Show()
app.MainLoop()
EDIT: This is not the same question as is proposed. In the proposed question, I used the hide and show method, and there was also a resizing problem, but there the panel was to big. I actually solved the other question and I will add the answer.

This post helped me with my problem (http://forums.devshed.com/python-programming-11/wxpython-refreshing-panel-panel-392700.html)
With adding
self.Fit()
self.GetParent().SendSizeEvent()
my problem was solved.

Related

how to differentiate background from foreground in pyqt5

I am trying to differentiate bits of background from foreground image in pyqt5.I am splitting the Qgraphicitem into bits and saving it as png image based on 16*16 pixel grids
I have tried the following code
[![from PyQt5.QtCore import (QByteArray, QDataStream, QIODevice,QObject, QMimeData, QPointF, QPoint, Qt,pyqtProperty, QRect,QTimer,QLineF, QEvent,QRectF)
from PyQt5.QtGui import QColor, QDrag, QPainter, QPixmap,QFont,QFontMetrics,QBrush, QLinearGradient, QIcon, QPen, QPainterPath,QKeySequence, QTransform,QCursor,QMouseEvent,QClipboard
from PyQt5.QtWidgets import QSplitterHandle,QApplication,QGraphicsScene,QGraphicsView,QWidget,QFontDialog,QHBoxLayout,QLabel,QMenu ,QGraphicsTextItem,QColorDialog,QGraphicsItemGroup,QGraphicsPixmapItem,QGraphicsRectItem,QMessageBox, QFormLayout,QSizePolicy, QScrollArea,QShortcut, QPushButton,QDialogButtonBox,QGroupBox,QLineEdit, QMainWindow,QInputDialog, QGraphicsPathItem,QDialog, QVBoxLayout,QGraphicsItem,QStatusBar
class GraphicsSceneClass(QGraphicsScene):
global selectedObjType
def __init__(self, parent=None):
super(GraphicsSceneClass, self).__init__(parent)
self.gridOn = 0
self.setSceneRect(0, 0, 1920, 1080)
self.setItemIndexMethod(QGraphicsScene.NoIndex)
self.setBackgroundBrush(QBrush(Qt.black))
def mousePressEvent(self, event):
sampleTransform = QTransform()
objectAtMouse = self.itemAt(event.scenePos(), sampleTransform)
if objectAtMouse and event.button()== Qt.LeftButton:
objectAtMouse.setSelected(True)
elif objectAtMouse==None and event.button()==Qt.RightButton:
# pass
self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
def TargPosForLine(self, position, mode):
clicked_column = int((position.y() // 16)) * 16
clicked_row = int((position.x() // 16)) * 16
if clicked_column < 0:
clicked_column = 0
if clicked_row < 0:
clicked_row = 0
if (mode == "ForRect"):
return QRect(clicked_row, clicked_column, 16, 16)
elif (mode == "ForLine"):
return QPointF(clicked_row, clicked_column)
def DeselectItems(self):
selectedObjects = self.selectedItems()
for object in selectedObjects:
object.setSelected(False)
def mouseReleaseEvent(self, event):
# self.DeselectItems()
pass
def textassign(self):
self.dialog = QDialog()
self.Gearname = QLabel("Name")
self.Gearnameedit = QLineEdit()
buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
buttonBox.accepted.connect(self.accept)
# buttonBox.rejected.connect(self.reject)
hbox = QFormLayout()
hbox.addRow(self.Gearname, self.Gearnameedit)
hbox.addRow(buttonBox)
self.dialog.setLayout(hbox)
self.dialog.exec()
def accept(self):
text = self.Gearnameedit.text()
# self.objectdrop._text
self.font = QFont()
self.font.setPixelSize(20)
self.font.setBold(False)
self.font.setFamily("Arial Unicode MS")
self.text = QGraphicsTextItem()
self.text.setPlainText(str(text))
self.text.setFont(self.font)
self.text.setDefaultTextColor(Qt.darkGreen)
self.addItem(self.text)
self.text.setPos(self.grid.x() + 20, self.grid.y() - 35)
# print("y", y)
self.text.setFlag(QGraphicsItem.ItemIsSelectable)
self.text.setFlag(QGraphicsItem.ItemIsMovable)
self.text.setFlag(QGraphicsItem.ItemIgnoresTransformations)
# self.objectdrop.setFlag(QGraphicsItem.ItemIsSelectable)
# self.text._position = QPointF(y.x() + 20, y.y() - 35)
self.text._type1 = "Text"
self.text._txtvalue = text
print(self.text._txtvalue)
self.dialog.close()
def createbitmap(self,objectDrop,gridPos):
w = 0
h = 0
self.objectdrop = objectDrop
pixmap = QPixmap(objectDrop._width, objectDrop._height)
pixmap.fill(Qt.transparent)
painter1 = QPainter(pixmap)
painter1.setPen(Qt.NoPen)
painter1.setBrush(objectDrop.brush())
# painter1.setClipPath(objectDrop.path())
painter1.setRenderHint(QPainter.HighQualityAntialiasing)
# painter1.setOpacity(0.5)
painter1.setBackgroundMode(0)
painter1.drawPath(objectDrop.path())
count = objectDrop._width // 16
pixmap.save("point.png")
# mid = self.TargPosForLine(objectDrop._midPos, "ForRect")
rect = QRect(16,0, 16, 16)
cropped = QPixmap(pixmap.copy(rect))
cropped.save("bit.png")
class MainWindow(QMainWindow):
global selectedObjType
# global item
def __init__(self, ):
super(MainWindow, self).__init__()
#
self.scene = GraphicsSceneClass()
MainWindow.obj = self.scene
self.view = QGraphicsView(self.scene)
# self.view.setDragMode(QGraphicsView.RubberBandDrag)
self.view.setMouseTracking(True)
self.view.setRenderHint(QPainter.HighQualityAntialiasing)
self.widg = QWidget()
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.view)
self.widg.setMouseTracking(True)
self.widget = QWidget()
self.widget.setLayout(self.horizontalLayout)
self.setCentralWidget(self.widget)
self.obj = None
def deleteItem(self):
for item in self.scene.selectedItems():
self.scene.removeItem(item)
def selectAll(self):
for item in self.scene.items():
item.setSelected(True)
def GridOnOffControl(self):
if self.scene.gridOn == 0:
self.scene.gridOn = 1
else:
self.scene.gridOn = 0
if self.scene.gridOn == 1:
self.scene.setBackgroundBrush(QBrush(QPixmap('images/Grid.png')))
else:
self.scene.setBackgroundBrush(QBrush(Qt.black))
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
Cutaction = contextMenu.addAction("Cut")
Coaction = contextMenu.addAction("Copy")
Paaction = contextMenu.addAction("Paste")
Propaction = contextMenu.addAction("draw1")
quitAct = contextMenu.addAction("quit")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
self.close()
elif action == Propaction:
objectDrop = None
painterPath = QPainterPath()
painterPath.moveTo(10.0, 0.0)
painterPath.arcTo(0.0, 0.0, 4.0, 4.0, 90.0, 90.0)
painterPath.lineTo(0.0, 4.0)
painterPath.arcTo(0.0, 2.0, 4.0, 4.0, 180.0, 90.0)
painterPath.lineTo(112 - 6, 6.0)
painterPath.arcTo(112 - 8, 2.0, 4.0, 4.0, 270.0, 90.0)
painterPath.lineTo(112 - 4, 2.0)
painterPath.arcTo(112 - 8, 0.0, 4.0, 4.0, 0.0, 90.0)
gradient = QLinearGradient(1, 1, 1, 5)
gradient.setColorAt(0, QColor(Qt.gray))
gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
gradient.setColorAt(1, QColor(Qt.darkGray))
painterPath.closeSubpath()
objectDrop = QGraphicsPathItem()
objectDrop.setPath(painterPath)
objectDrop.setBrush(QBrush(gradient))
objectDrop.setPos(self.scene.grid)
objectDrop._positon=QPointF(self.scene.grid.x(),self.scene.grid.y())
objectDrop._endPos=QPointF(objectDrop._positon.x()+112,objectDrop._positon.y())
objectDrop._width=objectDrop._endPos.x()-objectDrop._positon.x()
objectDrop._height=16
self.scene.addItem(objectDrop)
objectDrop.setFlag(QGraphicsItem.ItemIsSelectable)
objectDrop.setFlag(QGraphicsItem.ItemIsMovable)
self.scene.textassign()
self.scene.createbitmap(objectDrop,self.scene.grid)
def selectedItem(self):
items = self.scene.selectedItems()
if len(items) == 1:
return items\[0\]
return None
if __name__=="__main__":
import sys
app=QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())][1]][1]
If i give rect = QRect(16,0, 16, 16)it will give image 1
if rect = QRect(0,16,16,16) it will give image2
I want to neglect image2 kind of images.i.e images with only background

how to make copy paste to follow the same pattern

I am creating a design with my QGraphicsitems . I have selected all the items in the scene and pasted it.But it is not following the same pattern.can we make the items paste in the same pattern like the one which we have created initially? –
I have tried with the following code
from PyQt5.QtCore import (QByteArray,QDataStream, QIODevice,pyqtSlot, QMimeData, QPointF, QPoint, Qt, QRect,QTimer,QLineF, QEvent,QRectF)
from PyQt5.QtGui import QColor,QDrag, QPainter, QPixmap,QFont,QFontMetrics,QBrush, QLinearGradient, QIcon, QPen, QPainterPath, QTransform,QCursor,QMouseEvent,QClipboard
from PyQt5.QtWidgets import QApplication,QGraphicsTextItem,QGraphicsItemGroup, QSizePolicy,QShortcut, QScrollArea, QPushButton,QLineEdit, QMainWindow,QInputDialog, QGraphicsPathItem,QDialog, QVBoxLayout,QGraphicsItem,QStatusBar,QTextEdit, QAction,QMenu, qApp,QSplitter, QButtonGroup, QToolButton, QFrame, QHBoxLayout, QGraphicsView, QGraphicsItem, QGraphicsPixmapItem, QLabel, QGraphicsScene, QWidget
import importlib
import SketchBook as sketchBook
import Blocks as blocks
import random
custom_mimeType = "application/x-qgraphicsitems"
pos1 = QPointF()
def item_to_ds(it, ds):
if not isinstance(it, QGraphicsItem):
return
ds.writeQString(it.__class__.__module__)
ds.writeQString(it.__class__.__name__)
ds.writeInt(it.flags())
ds << it.pos()
posdiff = it.pos().x() -pos1().x()
pos1 = QPointF(it.pos().x(),it.pos().y())
# ds.writeInt(it.UserType)
ds.writeFloat(it.opacity())
ds.writeFloat(it.rotation())
ds.writeFloat(it.scale())
# ds.writeString(it.type())
# ds.writeQString(it.type1())
# if isinstance(it, QGraphicsItem):
# ds << it.brush() << it.pen()
if isinstance(it, QGraphicsPixmapItem):
ds << it.pixmap()
if isinstance(it, QGraphicsPathItem):
ds << it.path()
def ds_to_item(ds):
module_name = ds.readQString()
class_name = ds.readQString()
if class_name == 'QGraphicsPixmapItem':
mod = importlib.import_module(module_name)
it = getattr(mod, class_name)()
# flags = QGraphicsItem.GraphicsItemFlag(ds.readInt())
# pos = QPointF()
# ds >> pos
# it.setFlags(flags)
# it.setPos(pos)
# it.setOpacity(ds.readFloat())
# it.setRotation(ds.readFloat())
# it.setScale(ds.readFloat())
else:
mod = importlib.import_module(module_name)
it = getattr(mod, class_name)(blocks.selectedObjType)
flags = QGraphicsItem.GraphicsItemFlag(ds.readInt())
pos = QPointF()
ds >> pos
it.setFlags(flags)
it.setPos(pos)
it.setOpacity(ds.readFloat())
it.setRotation(ds.readFloat())
it.setScale(ds.readFloat())
# if isinstance(it, QGraphicsItem):
# pen, brush = QPen(), QBrush()
# ds >> brush
# ds >> pen
# it.setPen(pen)
# it.setBrush(brush)
if isinstance(it, QGraphicsPathItem):
path = QPainterPath()
ds >> path
it.setPath(path)
if isinstance(it, QGraphicsPixmapItem):
pixmap = QPixmap()
# pen, brush = QPen(), QBrush()
# ds >> brush
# ds >> pen
ds >> pixmap
it.setPixmap(pixmap)
return it
class GraphicsSceneClass(QGraphicsScene):
global selectedObjType
def __init__(self, parent=None):
super(GraphicsSceneClass, self).__init__(parent)
self.gridOn = 0
self.setSceneRect(0, 0, 1920, 1080)
self.setItemIndexMethod(QGraphicsScene.NoIndex)
self.setBackgroundBrush(QBrush(Qt.black))
def mousePressEvent(self, event):
sampleTransform = QTransform()
objectAtMouse = self.itemAt(event.scenePos(), sampleTransform)
if objectAtMouse and event.button()== Qt.LeftButton:
objectAtMouse.setSelected(True)
elif objectAtMouse==None and event.button()==Qt.RightButton:
# pass
self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
print(self.grid)
# else:
# self.DeselectItems()
# objectAtMouse.QShortcut
def TargPosForLine(self, position, mode):
clicked_column = int((position.y() // 16)) * 16
clicked_row = int((position.x() // 16)) * 16
if clicked_column < 0:
clicked_column = 0
if clicked_row < 0:
clicked_row = 0
if(mode == "ForRect"):
return QRect(clicked_row, clicked_column,16,16)
elif(mode == "ForLine"):
return QPointF(clicked_row,clicked_column)
def DeselectItems(self):
selectedObjects = self.selectedItems()
for object in selectedObjects:
object.setSelected(False)
def mouseReleaseEvent(self, event):
# self.DeselectItems()
pass
class MainWindow(QMainWindow):
global selectedObjType
# global item
def __init__(self,):
super(MainWindow, self).__init__()
self.createActions()
self.createMenus()
self.createToolbars()
self.scene = GraphicsSceneClass()
MainWindow.obj = self.scene
self.view = QGraphicsView(self.scene)
# self.view.setDragMode(QGraphicsView.RubberBandDrag)
self.view.setMouseTracking(True)
self.view.setRenderHint(QPainter.HighQualityAntialiasing)
self.widg = QWidget()
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.view)
self.widg.setMouseTracking(True)
self.widget = QWidget()
self.widget.setLayout(self.horizontalLayout)
self.setCentralWidget(self.widget)
self.obj=None
def createMenus(self):
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.exitAction)
fileMenu = menuBar.addMenu('&Edit')
fileMenu.addAction(self.copyAction)
fileMenu.addAction(self.pasteAction)
fileMenu.addAction(self.selectAction)
def createActions(self):
self.exitAction = QAction("E&xit", self, shortcut="Ctrl+X", statusTip="Quit Scenediagram example",
triggered=self.deleteItem)
self.copyAction = QAction("C&opy", self, shortcut="Ctrl+C", triggered=self.copy)
self.pasteAction = QAction("P&aste", self, shortcut="Ctrl+V", triggered=self.paste)
self.selectAction = QAction("S&electAll", self, shortcut="Ctrl+A", triggered=self.selectAll)
def createToolbars(self):
GridButton = QToolButton()
GridButton.setCheckable(True)
GridButton.setIcon(QIcon('images/GridButton.png'))
GridButton.clicked.connect(self.GridOnOffControl)
GridButton.setToolTip("Grid Control")
self.pointerToolbar = self.addToolBar("Pointer type")
self.pointerToolbar.addWidget(GridButton)
def deleteItem(self):
for item in self.scene.selectedItems():
self.scene.removeItem(item)
def selectAll(self):
for item in self.scene.items():
item.setSelected(True)
def GridOnOffControl(self):
if self.scene.gridOn == 0:
self.scene.gridOn = 1
else:
self.scene.gridOn = 0
if self.scene.gridOn == 1:
self.scene.setBackgroundBrush(QBrush(QPixmap('images/Grid.png')))
else:
self.scene.setBackgroundBrush(QBrush(Qt.black))
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
Cutaction = contextMenu.addAction("Cut")
Coaction = contextMenu.addAction("Copy")
Paaction = contextMenu.addAction("Paste")
Propaction = contextMenu.addAction("draw1")
Propaction1=contextMenu.addAction("draw2")
quitAct = contextMenu.addAction("quit")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
self.close()
elif action == Propaction:
objectDrop = None
# painterPath = QPainterPath()
#
# painterPath.moveTo(10, 50.0)
# painterPath.lineTo(50,50)
# painterPath.lineTo(50,55)
# painterPath.lineTo(10,55)
# gradient = QLinearGradient(1, 1, 1, 5)
# gradient.setColorAt(0, QColor(Qt.gray))
# gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
# gradient.setColorAt(1, QColor(Qt.darkGray))
# painterPath.closeSubpath()
#
# objectDrop = QGraphicsPathItem()
# objectDrop.setPath(painterPath)
# objectDrop.setBrush(QBrush(gradient))
objectDrop = QGraphicsPixmapItem(QPixmap("2AS_HG_RG.png"))
objectDrop.setPos(self.scene.grid)
print("sig",self.scene.grid)
# objectDrop._position = QPointF(gridPos.x() + 2, gridPos.y() + 5.9)
# objectDrop._type = "2AS_HG_RG"
objectDrop._type1 = "2AS_HG_RG"
self.scene.addItem(objectDrop)
objectDrop.setFlag(QGraphicsItem.ItemIsSelectable)
objectDrop.setFlag(QGraphicsItem.ItemIsMovable)
objectDrop._type1="2AS_HG_RG"
# self.scene.addPath(painterPath)
elif action==Propaction1:
objectDrop = None
selectedObjType = "line"
objectDrop = sketchBook.SketchBook(selectedObjType)
print("line",self.scene.grid)
objectDrop.setFlag(QGraphicsItem.ItemIsSelectable)
objectDrop.setFlag(QGraphicsItem.ItemIsMovable)
objectDrop._type1 = "line"
objectDrop.setPos(self.scene.grid.x(),self.scene.grid.y()-48+5)
self.scene.addItem(objectDrop)
elif action == Coaction:
self.copy()
elif action == Paaction:
self.paste()
#pyqtSlot()
def copy(self):
mimedata = QMimeData()
ba = QByteArray()
ds = QDataStream(ba, QIODevice.WriteOnly)
for it in self.scene.selectedItems():
self.posdiff=item_to_ds(it, ds)
mimedata.setData(custom_mimeType, ba)
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
#pyqtSlot()
def paste(self):
pos2=self.scene.grid
clipboard = QApplication.clipboard()
mimedata = clipboard.mimeData()
if mimedata.hasFormat(custom_mimeType):
ba = mimedata.data(custom_mimeType)
# STR = str(ba)
# QW = ba.capacity()
ds = QDataStream(ba)
while not ds.atEnd():
# for it in ds:
it = ds_to_item(ds)
if isinstance(it, QGraphicsPixmapItem):
self.scene.addItem(it)
it.setPos(pos2)
it._position = QPointF(pos2.x() + 2, pos2.y() + 5.9)
print("sig",it._position)
it._type1 = "2AS_HG_RG"
else:
gradient = QLinearGradient(1, 1, 1, 5)
gradient.setColorAt(0, QColor(Qt.gray))
gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
gradient.setColorAt(1, QColor(Qt.darkGray))
self.scene.addItem(it)
it.setBrush(QBrush(gradient))
it.setPos(pos2.x()+self.posdiff().x(),pos2.y()-48)
it._position = QPointF(pos2.x() + 2, pos2.y() + 5.9)
print(it._position)
# it.setFlags(QGraphicsItem.ItemIsSelectable)
# it._type1 = "line"
def selectedItem(self):
items = self.scene.selectedItems()
if len(items) == 1:
return items[0]
return None
if __name__=="__main__":
import sys
app=QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
1) select all the items or the items to be pasted
2) copy it
3) paste it
if we have design pattern have item1 followed by item2 followed by item3 with respective distance. When we copy and paste it it should follow the same pattern.
QGraphicsItem.setPos() is absolute to the scene (or relative to its parent), the alternative solution is to use moveBy(x, y) (which is the same as setPos(self.pos() + deltaPos), but you have to take into account the relative position of the click according to the reference point.
I'd suggest you to not set the position until all items have been added, and then set their position according to a specific item that will be used as an "anchor" point.
#pyqtSlot()
def paste(self):
pos2=self.scene.grid
clipboard = QApplication.clipboard()
mimedata = clipboard.mimeData()
items = []
topLeft = None
if mimedata.hasFormat(custom_mimeType):
ba = mimedata.data(custom_mimeType)
ds = QDataStream(ba)
while not ds.atEnd():
it = ds_to_item(ds)
items.append(it)
if not topLeft:
topLeft = it
elif it.y() < topLeft.y() or it.x() < topLeft.x():
# find a possible topmost/leftmost item
topLeft = it
# add items, but do not set their position here
# ...
delta = self.scene.grid - topLeft.pos()
[i.moveBy(delta.x(), delta.y()) for i in items]
An alternative is to find the "anchor" in the copy procedure, and set the position of each item relative to that point in the datastream, so that you'll be able to use moveBy(pos2.x(), pos2.y()) directly after adding the items.

ScrolledPanel not resizing after DestroyChildren

I got this code from a topic on Stackoverflow ScrolledPanel inside Panel not sizing. It works well for me. However I want to destroy all children of the scrolled_panel then recreate its new children. So I modify the code like this:
import wx
import wx.lib.scrolledpanel as scrolled
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial", size=(200,500))
self.n = 13
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
# --------------------
# Scrolled panel stuff
self.scrolled_panel = scrolled.ScrolledPanel(self.panel, -1,
style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER, name="panel1")
self.scrolled_panel.SetAutoLayout(1)
self.scrolled_panel.SetupScrolling()
words = "A Quick Brown Insane Fox Jumped Over the Fence and Ziplined to Cover".split()
self.spSizer = wx.BoxSizer(wx.VERTICAL)
for word in words:
text = wx.TextCtrl(self.scrolled_panel, value=word)
self.spSizer.Add(text)
self.scrolled_panel.SetSizer(self.spSizer)
# --------------------
btn = wx.Button(self.panel, label="Add Widget")
btn.Bind(wx.EVT_BUTTON, self.onAdd)
panelSizer = wx.BoxSizer(wx.VERTICAL)
panelSizer.AddSpacer(50)
panelSizer.Add(self.scrolled_panel, 1, wx.EXPAND)
panelSizer.Add(btn)
self.panel.SetSizer(panelSizer)
#----------------------------------------------------------------------
def onAdd(self, event):
""""""
print "in onAdd"
self.n += 1
self.scrolled_panel.DestroyChildren()
for i in range(self.n):
new_text = wx.TextCtrl(self.scrolled_panel, value="New Text %s" % i)
self.spSizer.Add(new_text)
#new_text = wx.TextCtrl(self.scrolled_panel, value="New Text")
#self.spSizer.Add(new_text)
self.scrolled_panel.Layout()
self.scrolled_panel.SetupScrolling()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm().Show()
app.MainLoop()
Now, even when I create the children more than the panel's size can show, I don't see the scroll bar as the original code. Can any one help me with this? Thanks ahead!!!
I solved this problem by adding testpanel to add scrolledPanel in it. Whennever onAdd() is call, after destroying all of testpanel's children, everything under the testpanel even the sizer have to be re-created and re-setup.
I've tried to do like that without the testpanel, I still could scroll by using my mouse, but didn't see the scrollbar, I don't know why. This is my new code:
import wx
import wx.lib.scrolledpanel as scrolled
########################################################################
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial", size=(200,500))
self.n =17
# Add a panel so it looks the correct on all platforms
self.panel = wx.Panel(self, wx.ID_ANY)
panelSizer = wx.BoxSizer(wx.VERTICAL)
panelSizer.AddSpacer(50)
# add a panel
self.testpanel = wx.Panel(self.panel, wx.ID_ANY)
#self.testpanel.SetSizer(self.testpanelSizer)
panelSizer.Add(self.testpanel, 1, wx.EXPAND)
self.onAdd()
btn = wx.Button(self.panel, label="Add Widget")
btn.Bind(wx.EVT_BUTTON, self.onAdd)
panelSizer.Add(btn)
self.panel.SetSizer(panelSizer)
#----------------------------------------------------------------------
def onAdd(self, event=None):
self.n +=1
self.testpanel.DestroyChildren()
testpanelSizer = wx.BoxSizer(wx.VERTICAL)
scrolled_panel = scrolled.ScrolledPanel(self.testpanel, -1,
style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER, name="panel1")
scrolled_panel.SetAutoLayout(1)
scrolled_panel.SetupScrolling()
spSizer = wx.BoxSizer(wx.VERTICAL)
for i in range(self.n):
new_text = wx.TextCtrl(scrolled_panel, value="New Text %s" % i)
spSizer.Add(new_text)
scrolled_panel.SetSizer(spSizer)
testpanelSizer.Add(scrolled_panel, 1, wx.EXPAND)
self.testpanel.SetSizer(testpanelSizer)
self.testpanel.Layout()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm().Show()
app.MainLoop()

How to rebuild panels in wxpython in function of a variable?

I searched a lot to do this but nothing of what I tried work. Now, as last attemp, I am trying with pubsub, but I can get nothing of worth, that's why I am asking for help now :). This is an minimal (as best I can do it :)) example of what I want. PanelB gets information in a list (box), and when someone of the items is selected, PanelA should change according to him.
Thank you in advance.
from wx.lib.pubsub import Publisher
import wx
global name
name = 'none, please select an item'
class PanelA(wx.Panel):
def __init__(self, parent, name):
wx.Panel.__init__(self, parent)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)
str = name
txt = wx.StaticText(self, -1, "You have selected " + str, (20, 100))
self.hbox.Add(txt, 1, wx.EXPAND | wx.ALL, 20)
class PanelB(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.listbox = wx.ListBox(self, -1)
self.hbox.Add(self.listbox, 1, wx.EXPAND | wx.ALL, 20)
self.btnPanel = wx.Panel(self, -1)
self.new = wx.Button(self.btnPanel,label='Add', size=(90, 30))
self.new.Bind(wx.EVT_BUTTON, self.NewItem)
self.vbox.Add((-1, 20))
self.vbox.Add(self.new)
self.btnPanel.SetSizer(self.vbox)
self.hbox.Add(self.btnPanel, 0.6, wx.EXPAND | wx.RIGHT, 20)
self.SetSizer(self.hbox)
self.Bind(wx.EVT_LISTBOX, self.onSelect)
def onSelect(self, event):
name_selected = self.listbox.GetStringSelection()
Publisher().sendMessage(("ListBox"), name_selected)
def NewItem(self, event):
text = wx.GetTextFromUser('Nombre', 'Programa a salvar')
if text != '':
self.listbox.Append(text)
class MainFrame(wx.Frame):
def __init__(self, parent, id, title, *args, **kw):
wx.Frame.__init__(self, parent, id, title, size = (800,300))
self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_3D)
self.lc1 = PanelB(self.splitter)
Publisher().subscribe(self.OnSelect, ("ListBox"))
self.lc2 = PanelA(self.splitter, name)
self.splitter.SplitVertically(self.lc1, self.lc2)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(self.splitter, 1, wx.EXPAND)
self.SetSizer(sizer)
self.Centre()
self.Show(True)
def OnSelect(self, name_selected):
name = name_selected
#I stucked here
if __name__ == "__main__":
app = wx.App()
frame = MainFrame(None,-1,'Mi aplicacion')
app.MainLoop()
This is not beautiful solution, basically you can just destroy PanelA then call that panel again, maybe like this:
def OnSelect(self, name_selected):
self.lc2.Destroy()
self.lc2 = PanelA(self.splitter, name_selected.data)
Hope this can help.
UPDATE (08/24/2012): added some code
Okey we should not destroy the panel. I'm using your code and modified it a bit. I removed global variable name and added changeName(name) function to PanelA so that when MainFrame.onSelect() is called it will call changeName(). It's not beautiful but hope this can help.
import wx
from wx.lib.pubsub import Publisher
class PanelA(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)
name = "none, please select an item"
self.txt = wx.StaticText(self, -1, "You have selected " + name,
(50, 100))
self.hbox.Add(self.txt, 1, wx.EXPAND|wx.ALL, 30)
def changeName(self, name):
self.hbox.Hide(self.txt)
self.hbox.Remove(self.txt)
self.txt = wx.StaticText(self, -1, "You have selected " + name, (50, 100))
self.hbox.Add(self.txt, 1, wx.EXPAND|wx.ALL, 30)
class PanelB(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.listbox = wx.ListBox(self, -1)
self.hbox.Add(self.listbox, 1, wx.EXPAND|wx.ALL, 20)
self.btnPanel = wx.Panel(self, -1)
self.new = wx.Button(self.btnPanel,label='Add', size=(90, 30))
self.new.Bind(wx.EVT_BUTTON, self.NewItem)
self.vbox.Add((-1, 20))
self.vbox.Add(self.new)
self.btnPanel.SetSizer(self.vbox)
self.hbox.Add(self.btnPanel, 0.6, wx.EXPAND|wx.RIGHT, 20)
self.SetSizer(self.hbox)
self.Bind(wx.EVT_LISTBOX, self.onSelect)
def onSelect(self, event):
name_selected = self.listbox.GetStringSelection()
Publisher().sendMessage("ListBox", name_selected)
def NewItem(self, event):
text = wx.GetTextFromUser('Nombre', 'Programa a salvar')
if text != '':
self.listbox.Append(text)
class MainFrame(wx.Frame):
def __init__(self, parent, id, title, *args, **kw):
wx.Frame.__init__(self, parent, id, title, size = (800,300))
self.splitter = wx.SplitterWindow(self, -1, style=wx.SP_3D)
Publisher().subscribe(self.OnSelect, "ListBox")
self.lc1 = PanelB(self.splitter)
self.lc2 = PanelA(self.splitter)
self.splitter.SplitVertically(self.lc1, self.lc2)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.splitter, 1, wx.EXPAND)
self.SetSizer(self.sizer)
self.Layout()
self.Centre()
def OnSelect(self, name_selected):
name = name_selected
self.lc2.changeName(name.data)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MainFrame(None,-1,'Mi aplicacion')
frame.Show()
app.MainLoop()

Problem setting value of wx.TextCtrl in wxPython

I'm trying to pass the directory the user chooses back to the wx.TextCtrl named ChooseRoot. This has not worked so far.
What am I doing wrong? I tried different things, but either it hangs or I get this error message.
Traceback (most recent call last):
File "F:\Indexinator3000_x64.pyw", line 78, in OnChooseRoot
self.ChooseRoot.SetValue("Hello")
AttributeError: 'MainPanel' object has no attribute 'ChooseRoot'
import wx
ID_EXIT = 110
class MainPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.parent = parent
#------------- Setting up the buttons
self.Run = wx.Button(self, label="Run")
self.Run.Bind(wx.EVT_BUTTON, self.OnRun )
self.ExitB = wx.Button(self, label="Exit")
self.ExitB.Bind(wx.EVT_BUTTON, self.OnExit)
#------------- Setting up Static text
self.labelChooseRoot = wx.StaticText(self, label ="Root catalog: ")
self.labelScratchWrk = wx.StaticText(self, label ="Sratch workspace: ")
self.labelMergeFile = wx.StaticText(self, label ="Merge file: ")
#------------ Setting up inputtext
self.ChooseRoot = wx.TextCtrl(self, -1, size=(210,-1))
self.ChooseRoot.Bind(wx.EVT_LEFT_UP, self.OnChooseRoot)
self.ScratchWrk = wx.TextCtrl(self, -1, size=(210,-1))
self.MergeFile = wx.TextCtrl(self, -1, size=(210,-1))
#------------- Setting up the outputbox
self.Output = wx.TextCtrl(self, style=wx.TE_MULTILINE|wx.TE_READONLY)
#------------- Setting up the sizer
SizerF = wx.FlexGridSizer(3,2,5,5)
SizerF.Add(labelChooseRoot) #row 1, col 1
SizerF.Add(ChooseRoot) #row 1, col 2
SizerF.Add(labelScratchWrk) #row 2, col 1
SizerF.Add(ScratchWrk) #row 2, col 2
SizerF.Add(labelMergeFile) #row 3, col 1
SizerF.Add(MergeFile) #row 3, col 2
SizerB = wx.BoxSizer(wx.VERTICAL)
SizerB.Add(Run, 1, wx.ALIGN_RIGHT|wx.ALL, 5)
SizerB.Add(ExitB, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
Sizer1 = wx.BoxSizer()
Sizer1.Add(SizerF, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 10)
Sizer1.Add(SizerB, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
Sizer2 = wx.BoxSizer()
Sizer2.Add(Output, 1, wx.EXPAND | wx.ALL, 5)
SizerFinal = wx.BoxSizer(wx.VERTICAL)
SizerFinal.Add(Sizer1, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
SizerFinal.Add(Sizer2, 1, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
self.SetSizerAndFit(SizerFinal)
#--- START EVENT HANDLERS
def OnChooseRoot(self, Event=None):
# In this case we include a "New directory" button.
dlg = wx.DirDialog(self, "Choose a directory:",
style=wx.DD_DEFAULT_STYLE
#| wx.DD_DIR_MUST_EXIST
#| wx.DD_CHANGE_DIR
)
# If the user selects OK, then we process the dialog's data.
# This is done by getting the path data from the dialog - BEFORE
# we destroy it.
if dlg.ShowModal() == wx.ID_OK:
RootPath = dlg.GetPath()
self.ChooseRoot.SetValue(RootPath)
# Only destroy a dialog after you're done with it.
dlg.Destroy()
def OnRun(self, Event=None):
#First check if any of the boxes is empty
pass
def OnExit(self, Event=None):
self.GetParent().Close()
#--- END EVENT HANDLERS
class MainWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, wx.ID_ANY, title, size = (430,330),
style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE | wx.STAY_ON_TOP)
self.CreateStatusBar()
#------------- Setting up the menu
filemenu = wx.Menu()
filemenu.Append(ID_EXIT, "E&xit", "Exit the program")
#------------- Creating the menu
menubar = wx.MenuBar()
menubar.Append(filemenu, "&File")
self.SetMenuBar(menubar)
#---------- Setting menu event handlers
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
#--- Add MainPanel
self.Panel = MainPanel(self, -1)
self.SetMaxSize(self.GetSize()) #Sets the Maximum size the window can have
self.SetMinSize(self.GetSize()) #Sets the Minimum size the window can have
#Centre on Screen
self.CentreOnScreen()
###---- SHOW THE WINDOW
self.Show(True)
def OnExit(self, event):
self.Close(True) # Close the Frame
#--- END EVENT HANDLERS ---------------------------------
if __name__=='__main__':
try:
app = wx.PySimpleApp()
frame = MainWindow(None, -1, "IndexGenerator")
app.MainLoop()
finally:
del app
Read carefully advices that I have given you in your previous question. Especially:
use object properties for the widgets, so you do not loose track of them (self.ChooseRoot =...)
use more desriptive widget names (self.labelChooseRoot)
Outside of the __init__ method (aka constructor) you loose track of your widgets. You have to add them to your MainPanel object as attributes.
class MainPanel(wx.Panel):
def __init__(self, parent, id):
...
self.ChooseRoot = wx.TextCtrl(self, size=(210, -1))
...
def OnChooseRoot(self, event=None):
...
self.ChooseRoot.SetValue(RootPath)
...
I would also recommend some reading on OOP concepts. Maybe you can start from here.
Edit:
You nearly got it working. The idea was OK, you just forgot a few places. I have updated your code to conform with my "standard", deleted some unnecessary copy/paste stuff and some other minor tweaks. Use some compare software and do a careful compare to see the changes if you like.
import wx
ID_EXIT = 110
class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.buttonRun = wx.Button(self, label="Run")
self.buttonRun.Bind(wx.EVT_BUTTON, self.OnRun )
self.buttonExit = wx.Button(self, label="Exit")
self.buttonExit.Bind(wx.EVT_BUTTON, self.OnExit)
self.labelChooseRoot = wx.StaticText(self, label ="Root catalog: ")
self.labelScratchWrk = wx.StaticText(self, label ="Scratch workspace: ")
self.labelMergeFile = wx.StaticText(self, label ="Merge file: ")
self.textChooseRoot = wx.TextCtrl(self, size=(210, -1))
self.textChooseRoot.Bind(wx.EVT_LEFT_UP, self.OnChooseRoot)
self.textScratchWrk = wx.TextCtrl(self, size=(210, -1))
self.textMergeFile = wx.TextCtrl(self, size=(210, -1))
self.textOutput = wx.TextCtrl(self, style=wx.TE_MULTILINE | wx.TE_READONLY)
self.sizerF = wx.FlexGridSizer(3, 2, 5, 5)
self.sizerF.Add(self.labelChooseRoot) #row 1, col 1
self.sizerF.Add(self.textChooseRoot) #row 1, col 2
self.sizerF.Add(self.labelScratchWrk) #row 2, col 1
self.sizerF.Add(self.textScratchWrk) #row 2, col 2
self.sizerF.Add(self.labelMergeFile) #row 3, col 1
self.sizerF.Add(self.textMergeFile) #row 3, col 2
self.sizerB = wx.BoxSizer(wx.VERTICAL)
self.sizerB.Add(self.buttonRun, 1, wx.ALIGN_RIGHT|wx.ALL, 5)
self.sizerB.Add(self.buttonExit, 0, wx.ALIGN_RIGHT|wx.ALL, 5)
self.sizer1 = wx.BoxSizer()
self.sizer1.Add(self.sizerF, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL, 10)
self.sizer1.Add(self.sizerB, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
self.sizer2 = wx.BoxSizer()
self.sizer2.Add(self.textOutput, 1, wx.EXPAND | wx.ALL, 5)
self.sizerFinal = wx.BoxSizer(wx.VERTICAL)
self.sizerFinal.Add(self.sizer1, 0, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
self.sizerFinal.Add(self.sizer2, 1, wx.ALIGN_RIGHT | wx.EXPAND | wx.ALL)
self.SetSizerAndFit(self.sizerFinal)
def OnChooseRoot(self, event):
dlg = wx.DirDialog(self, "Choose a directory:", style=wx.DD_DEFAULT_STYLE)
if dlg.ShowModal() == wx.ID_OK:
root_path = dlg.GetPath()
self.textChooseRoot.SetValue(root_path)
dlg.Destroy()
def OnRun(self, event):
#First check if any of the boxes is empty
pass
def OnExit(self, event):
self.GetParent().Close()
class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="IndexGenerator", size=(430, 330),
style=((wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE |
wx.STAY_ON_TOP) ^ wx.RESIZE_BORDER))
self.CreateStatusBar()
self.fileMenu = wx.Menu()
self.fileMenu.Append(ID_EXIT, "E&xit", "Exit the program")
self.menuBar = wx.MenuBar()
self.menuBar.Append(self.fileMenu, "&File")
self.SetMenuBar(self.menuBar)
wx.EVT_MENU(self, ID_EXIT, self.OnExit)
self.Panel = MainPanel(self)
self.CentreOnScreen()
self.Show()
def OnExit(self, event):
self.Close()
if __name__ == "__main__":
app = wx.App(False)
frame = MainWindow()
app.MainLoop()