Commit 885d2157 authored by Megan Kratz's avatar Megan Kratz
Browse files

merge from luke

parents c039074e 450626a3
......@@ -77,6 +77,11 @@ class Dock(QtGui.QWidget, DockDrop):
return name == 'dock'
def setStretch(self, x=None, y=None):
"""
Set the 'target' size for this Dock.
The actual size will be determined by comparing this Dock's
stretch value to the rest of the docks it shares space with.
"""
#print "setStretch", self, x, y
#self._stretch = (x, y)
if x is None:
......@@ -100,6 +105,10 @@ class Dock(QtGui.QWidget, DockDrop):
#return self._stretch
def hideTitleBar(self):
"""
Hide the title bar for this Dock.
This will prevent the Dock being moved by the user.
"""
self.label.hide()
self.labelHidden = True
if 'center' in self.allowedAreas:
......@@ -107,12 +116,21 @@ class Dock(QtGui.QWidget, DockDrop):
self.updateStyle()
def showTitleBar(self):
"""
Show the title bar for this Dock.
"""
self.label.show()
self.labelHidden = False
self.allowedAreas.add('center')
self.updateStyle()
def setOrientation(self, o='auto', force=False):
"""
Sets the orientation of the title bar for this Dock.
Must be one of 'auto', 'horizontal', or 'vertical'.
By default ('auto'), the orientation is determined
based on the aspect ratio of the Dock.
"""
#print self.name(), "setOrientation", o, force
if o == 'auto' and self.autoOrient:
if self.container().type() == 'tab':
......@@ -127,6 +145,7 @@ class Dock(QtGui.QWidget, DockDrop):
self.updateStyle()
def updateStyle(self):
## updates orientation and appearance of title bar
#print self.name(), "update style:", self.orientation, self.moveLabel, self.label.isVisible()
if self.labelHidden:
self.widgetArea.setStyleSheet(self.nStyle)
......@@ -154,6 +173,10 @@ class Dock(QtGui.QWidget, DockDrop):
return self._container
def addWidget(self, widget, row=None, col=0, rowspan=1, colspan=1):
"""
Add a new widget to the interior of this Dock.
Each Dock uses a QGridLayout to arrange widgets within.
"""
if row is None:
row = self.currentRow
self.currentRow = max(row+1, self.currentRow)
......@@ -188,7 +211,8 @@ class Dock(QtGui.QWidget, DockDrop):
def __repr__(self):
return "<Dock %s %s>" % (self.name(), self.stretch())
class DockLabel(VerticalLabel):
sigClicked = QtCore.Signal(object, object)
......@@ -287,76 +311,3 @@ class DockLabel(VerticalLabel):
#class DockLabel(QtGui.QWidget):
#def __init__(self, text, dock):
#QtGui.QWidget.__init__(self)
#self._text = text
#self.dock = dock
#self.orientation = None
#self.setOrientation('horizontal')
#def text(self):
#return self._text
#def mousePressEvent(self, ev):
#if ev.button() == QtCore.Qt.LeftButton:
#self.pressPos = ev.pos()
#self.startedDrag = False
#ev.accept()
#def mouseMoveEvent(self, ev):
#if not self.startedDrag and (ev.pos() - self.pressPos).manhattanLength() > QtGui.QApplication.startDragDistance():
#self.dock.startDrag()
#ev.accept()
##print ev.pos()
#def mouseReleaseEvent(self, ev):
#ev.accept()
#def mouseDoubleClickEvent(self, ev):
#if ev.button() == QtCore.Qt.LeftButton:
#self.dock.float()
#def setOrientation(self, o):
#if self.orientation == o:
#return
#self.orientation = o
#self.update()
#self.updateGeometry()
#def paintEvent(self, ev):
#p = QtGui.QPainter(self)
#p.setBrush(QtGui.QBrush(QtGui.QColor(100, 100, 200)))
#p.setPen(QtGui.QPen(QtGui.QColor(50, 50, 100)))
#p.drawRect(self.rect().adjusted(0, 0, -1, -1))
#p.setPen(QtGui.QPen(QtGui.QColor(255, 255, 255)))
#if self.orientation == 'vertical':
#p.rotate(-90)
#rgn = QtCore.QRect(-self.height(), 0, self.height(), self.width())
#else:
#rgn = self.rect()
#align = QtCore.Qt.AlignTop|QtCore.Qt.AlignHCenter
#self.hint = p.drawText(rgn, align, self.text())
#p.end()
#if self.orientation == 'vertical':
#self.setMaximumWidth(self.hint.height())
#self.setMaximumHeight(16777215)
#else:
#self.setMaximumHeight(self.hint.height())
#self.setMaximumWidth(16777215)
#def sizeHint(self):
#if self.orientation == 'vertical':
#if hasattr(self, 'hint'):
#return QtCore.QSize(self.hint.height(), self.hint.width())
#else:
#return QtCore.QSize(19, 50)
#else:
#if hasattr(self, 'hint'):
#return QtCore.QSize(self.hint.width(), self.hint.height())
#else:
#return QtCore.QSize(50, 19)
......@@ -35,8 +35,18 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
def addDock(self, dock, position='bottom', relativeTo=None):
"""Adds a dock to this area.
position may be: bottom, top, left, right, over, under
If relativeTo specifies an existing dock, the new dock is added adjacent to it"""
=========== =================================================================
Arguments:
dock The new Dock object to add.
position 'bottom', 'top', 'left', 'right', 'over', or 'under'
relativeTo If relativeTo is None, then the new Dock is added to fill an
entire edge of the window. If relativeTo is another Dock, then
the new Dock is placed adjacent to it (or in a tabbed
configuration for 'over' and 'under').
=========== =================================================================
"""
## Determine the container to insert this dock into.
## If there is no neighbor, then the container is the top.
......@@ -90,6 +100,17 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
dock.area = self
self.docks[dock.name()] = dock
def moveDock(self, dock, position, neighbor):
"""
Move an existing Dock to a new location.
"""
old = dock.container()
## Moving to the edge of a tabbed dock causes a drop outside the tab box
if position in ['left', 'right', 'top', 'bottom'] and neighbor is not None and neighbor.container() is not None and neighbor.container().type() == 'tab':
neighbor = neighbor.container()
self.addDock(dock, position, neighbor)
old.apoptose()
def getContainer(self, obj):
if obj is None:
return self
......@@ -131,13 +152,6 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
return 0
return 1
def moveDock(self, dock, position, neighbor):
old = dock.container()
## Moving to the edge of a tabbed dock causes a drop outside the tab box
if position in ['left', 'right', 'top', 'bottom'] and neighbor is not None and neighbor.container() is not None and neighbor.container().type() == 'tab':
neighbor = neighbor.container()
self.addDock(dock, position, neighbor)
old.apoptose()
#def paintEvent(self, ev):
#self.drawDockOverlay()
......@@ -159,6 +173,7 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
return area
def floatDock(self, dock):
"""Removes *dock* from this DockArea and places it in a new window."""
area = self.addTempArea()
area.win.resize(dock.size())
area.moveDock(dock, 'top', None)
......@@ -170,6 +185,9 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
area.window().close()
def saveState(self):
"""
Return a serialized (storable) representation of the state of
all Docks in this DockArea."""
state = {'main': self.childState(self.topContainer), 'float': []}
for a in self.tempAreas:
geo = a.win.geometry()
......@@ -188,6 +206,10 @@ class DockArea(Container, QtGui.QWidget, DockDrop):
def restoreState(self, state):
"""
Restore Dock configuration as generated by saveState.
"""
## 1) make dict of all docks and list of existing containers
containers, docks = self.findAll()
oldTemps = self.tempAreas[:]
......
GLImageItem
===========
.. autoclass:: pyqtgraph.opengl.GLImageItem
:members:
.. automethod:: pyqtgraph.opengl.GLImageItem.__init__
GLScatterPlotItem
=================
.. autoclass:: pyqtgraph.opengl.GLScatterPlotItem
:members:
.. automethod:: pyqtgraph.opengl.GLScatterPlotItem.__init__
......@@ -18,7 +18,9 @@ Contents:
glgriditem
glmeshitem
glvolumeitem
glimageitem
glaxisitem
glgraphicsitem
glscatterplotitem
meshdata
......@@ -29,6 +29,7 @@ Contents:
scalebar
labelitem
vtickgroup
legenditem
gradienteditoritem
histogramlutitem
gradientlegend
......
LegendItem
==========
.. autoclass:: pyqtgraph.LegendItem
:members:
.. automethod:: pyqtgraph.LegendItem.__init__
# -*- coding: utf-8 -*-
## Add path to library (just for examples; you do not need this)
import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import pyqtgraph as pg
import numpy as np
import scipy.ndimage as ndi
app = QtGui.QApplication([])
w = gl.GLViewWidget()
w.opts['distance'] = 200
w.show()
## create volume data set to slice three images from
shape = (100,100,70)
data = ndi.gaussian_filter(np.random.normal(size=shape), (4,4,4))
data += ndi.gaussian_filter(np.random.normal(size=shape), (15,15,15))*15
## slice out three planes, convert to ARGB for OpenGL texture
levels = (-0.08, 0.08)
tex1 = pg.makeRGBA(data[shape[0]/2], levels=levels)[0] # yz plane
tex2 = pg.makeRGBA(data[:,shape[1]/2], levels=levels)[0] # xz plane
tex3 = pg.makeRGBA(data[:,:,shape[2]/2], levels=levels)[0] # xy plane
## Create three image items from textures, add to view
v1 = gl.GLImageItem(tex1)
v1.translate(-shape[1]/2, -shape[2]/2, 0)
v1.rotate(90, 0,0,1)
v1.rotate(-90, 0,1,0)
w.addItem(v1)
v2 = gl.GLImageItem(tex2)
v2.translate(-shape[0]/2, -shape[2]/2, 0)
v2.rotate(-90, 1,0,0)
w.addItem(v2)
v3 = gl.GLImageItem(tex3)
v3.translate(-shape[0]/2, -shape[1]/2, 0)
w.addItem(v3)
ax = gl.GLAxisItem()
w.addItem(ax)
## Start Qt event loop unless running in interactive mode.
if sys.flags.interactive != 1:
app.exec_()
......@@ -5,6 +5,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph.opengl as gl
import numpy as np
app = QtGui.QApplication([])
w = gl.GLViewWidget()
......@@ -14,18 +15,47 @@ w.show()
g = gl.GLGridItem()
w.addItem(g)
pts = [
{'pos': (1,0,0), 'size':0.5, 'color':(1.0, 0.0, 0.0, 0.5)},
{'pos': (0,1,0), 'size':0.2, 'color':(0.0, 0.0, 1.0, 0.5)},
{'pos': (0,0,1), 'size':2./3., 'color':(0.0, 1.0, 0.0, 0.5)},
]
z = 0.5
d = 6.0
for i in range(50):
pts.append({'pos': (0,0,z), 'size':2./d, 'color':(0.0, 1.0, 0.0, 0.5)})
z *= 0.5
d *= 2.0
sp = gl.GLScatterPlotItem(pts)
#pos = np.empty((53, 3))
#size = np.empty((53))
#color = np.empty((53, 4))
#pos[0] = (1,0,0); size[0] = 0.5; color[0] = (1.0, 0.0, 0.0, 0.5)
#pos[1] = (0,1,0); size[1] = 0.2; color[1] = (0.0, 0.0, 1.0, 0.5)
#pos[2] = (0,0,1); size[2] = 2./3.; color[2] = (0.0, 1.0, 0.0, 0.5)
#z = 0.5
#d = 6.0
#for i in range(3,53):
#pos[i] = (0,0,z)
#size[i] = 2./d
#color[i] = (0.0, 1.0, 0.0, 0.5)
#z *= 0.5
#d *= 2.0
#sp = gl.GLScatterPlotItem(pos=pos, sizes=size, colors=color, pxMode=False)
pos = (np.random.random(size=(100000,3)) * 10) - 5
color = np.ones((pos.shape[0], 4))
d = (pos**2).sum(axis=1)**0.5
color[:,3] = np.clip(-np.cos(d*2) * 0.2, 0, 1)
sp = gl.GLScatterPlotItem(pos=pos, color=color, size=5)
phase = 0.
def update():
global phase, color, sp, d
s = -np.cos(d*2+phase)
color[:,3] = np.clip(s * 0.2, 0, 1)
color[:,0] = np.clip(s * 3.0, 0, 1)
color[:,1] = np.clip(s * 1.0, 0, 1)
color[:,2] = np.clip(s ** 3, 0, 1)
sp.setData(color=color)
phase -= 0.1
t = QtCore.QTimer()
t.timeout.connect(update)
t.start(50)
w.addItem(sp)
## Start Qt event loop unless running in interactive mode.
......
# -*- coding: utf-8 -*-
import initExample ## Add path to library (just for examples; you do not need this)
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
plt = pg.plot()
l = pg.LegendItem((100,60), (60,10)) # args are (size, position)
l.setParentItem(plt.graphicsItem()) # Note we do NOT call plt.addItem in this case
c1 = plt.plot([1,3,2,4], pen='r')
c2 = plt.plot([2,1,4,3], pen='g')
l.addItem(c1, 'red plot')
l.addItem(c2, 'green plot')
## Start Qt event loop unless running in interactive mode or using pyside.
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
......@@ -26,7 +26,7 @@ win.show()
p = ui.plot
data = np.random.normal(size=(50,500), scale=100)
sizeArray = np.random.random(500) * 20.
sizeArray = (np.random.random(500) * 20.).astype(int)
ptr = 0
lastTime = time()
fps = None
......@@ -49,7 +49,8 @@ def update():
s = np.clip(dt*3., 0, 1)
fps = fps * (1-s) + (1.0/dt) * s
p.setTitle('%0.2f fps' % fps)
app.processEvents() ## force complete redraw for every plot
p.repaint()
#app.processEvents() ## force complete redraw for every plot
timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(0)
......
......@@ -17,12 +17,11 @@ examples = OrderedDict([
('ImageView', 'ImageView.py'),
('ParameterTree', 'parametertree.py'),
('Crosshair / Mouse interaction', 'crosshair.py'),
('Video speed test', 'VideoSpeedTest.py'),
('Plot speed test', 'PlotSpeedTest.py'),
('Data Slicing', 'DataSlicing.py'),
('Plot Customization', 'customPlot.py'),
('Dock widgets', 'dockarea.py'),
('Console', 'ConsoleWidget.py'),
('Histograms', 'histogram.py'),
('GraphicsItems', OrderedDict([
('Scatter Plot', 'ScatterPlot.py'),
#('PlotItem', 'PlotItem.py'),
......@@ -31,14 +30,22 @@ examples = OrderedDict([
('ImageItem - draw', 'Draw.py'),
('Region-of-Interest', 'ROIExamples.py'),
('GraphicsLayout', 'GraphicsLayout.py'),
('LegendItem', 'Legend.py'),
('Text Item', 'text.py'),
('Linked Views', 'linkedViews.py'),
('Arrow', 'Arrow.py'),
('ViewBox', 'ViewBox.py'),
])),
('Benchmarks', OrderedDict([
('Video speed test', 'VideoSpeedTest.py'),
('Line Plot update', 'PlotSpeedTest.py'),
('Scatter Plot update', 'ScatterPlotSpeedTest.py'),
])),
('3D Graphics', OrderedDict([
('Volumetric', 'GLVolumeItem.py'),
('Isosurface', 'GLMeshItem.py'),
('Image', 'GLImageItem.py'),
('Scatter Plot', 'GLScatterPlotItem.py'),
])),
('Widgets', OrderedDict([
('PlotWidget', 'PlotWidget.py'),
......@@ -80,7 +87,17 @@ class ExampleLoader(QtGui.QMainWindow):
self.ui.loadBtn.clicked.connect(self.loadFile)
self.ui.exampleTree.currentItemChanged.connect(self.showFile)
self.ui.exampleTree.itemDoubleClicked.connect(self.loadFile)
self.ui.pyqtCheck.toggled.connect(self.pyqtToggled)
self.ui.pysideCheck.toggled.connect(self.pysideToggled)
def pyqtToggled(self, b):
if b:
self.ui.pysideCheck.setChecked(False)
def pysideToggled(self, b):
if b:
self.ui.pyqtCheck.setChecked(False)
def populateTree(self, root, examples):
for key, val in examples.items():
......@@ -101,12 +118,19 @@ class ExampleLoader(QtGui.QMainWindow):
def loadFile(self):
fn = self.currentFile()
extra = []
if self.ui.pyqtCheck.isChecked():
extra.append('pyqt')
elif self.ui.pysideCheck.isChecked():
extra.append('pyside')
if fn is None:
return
if sys.platform.startswith('win'):
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, '"' + fn + '"')
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, '"' + fn + '"', *extra)
else:
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, fn)
os.spawnl(os.P_NOWAIT, sys.executable, sys.executable, fn, *extra)
def showFile(self):
......
......@@ -39,6 +39,24 @@
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="pyqtCheck">
<property name="text">
<string>Force PyQt</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="pysideCheck">
<property name="text">
<string>Force PySide</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="loadBtn">
<property name="text">
......
......@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file './examples/exampleLoaderTemplate.ui'
#
# Created: Sun Sep 9 14:41:31 2012
# Created: Fri Oct 26 07:53:55 2012
# by: PyQt4 UI code generator 4.9.1
#
# WARNING! All changes made in this file will be lost!
......@@ -35,6 +35,15 @@ class Ui_Form(object):
self.exampleTree.headerItem().setText(0, _fromUtf8("1"))
self.exampleTree.header().setVisible(False)
self.verticalLayout.addWidget(self.exampleTree)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.pyqtCheck = QtGui.QCheckBox(self.layoutWidget)
self.pyqtCheck.setObjectName(_fromUtf8("pyqtCheck"))
self.horizontalLayout.addWidget(self.pyqtCheck)
self.pysideCheck = QtGui.QCheckBox(self.layoutWidget)
self.pysideCheck.setObjectName(_fromUtf8("pysideCheck"))
self.horizontalLayout.addWidget(self.pysideCheck)
self.verticalLayout.addLayout(self.horizontalLayout)
self.loadBtn = QtGui.QPushButton(self.layoutWidget)
self.loadBtn.setObjectName(_fromUtf8("loadBtn"))
self.verticalLayout.addWidget(self.loadBtn)
......@@ -51,5 +60,7 @@ class Ui_Form(object):
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.pyqtCheck.setText(QtGui.QApplication.translate("Form", "Force PyQt", None, QtGui.QApplication.UnicodeUTF8))
self.pysideCheck.setText(QtGui.QApplication.translate("Form", "Force PySide", None, QtGui.QApplication.UnicodeUTF8))
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load Example", None, QtGui.QApplication.UnicodeUTF8))
......@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file './examples/exampleLoaderTemplate.ui'
#
# Created: Sun Sep 9 14:41:31 2012
# Created: Fri Oct 26 07:53:57 2012
# by: pyside-uic 0.2.13 running on PySide 1.1.0
#
# WARNING! All changes made in this file will be lost!
......@@ -30,6 +30,15 @@ class Ui_Form(object):
self.exampleTree.headerItem().setText(0, "1")
self.exampleTree.header().setVisible(False)
self.verticalLayout.addWidget(self.exampleTree)
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.pyqtCheck = QtGui.QCheckBox(self.layoutWidget)
self.pyqtCheck.setObjectName("pyqtCheck")
self.horizontalLayout.addWidget(self.pyqtCheck)
self.pysideCheck = QtGui.QCheckBox(self.layoutWidget)
self.pysideCheck.setObjectName("pysideCheck")
self.horizontalLayout.addWidget(self.pysideCheck)
self.verticalLayout.addLayout(self.horizontalLayout)
self.loadBtn = QtGui.QPushButton(self.layoutWidget)
self.loadBtn.setObjectName("loadBtn")
self.verticalLayout.addWidget(self.loadBtn)
......@@ -46,5 +55,7 @@ class Ui_Form(object):
def retranslateUi(self, Form):
Form.setWindowTitle(QtGui.QApplication.translate("Form", "Form", None, QtGui.QApplication.UnicodeUTF8))
self.pyqtCheck.setText(QtGui.QApplication.translate("Form", "Force PyQt", None, QtGui.QApplication.UnicodeUTF8))
self.pysideCheck.setText(QtGui.QApplication.translate("Form", "Force PySide", None, QtGui.QApplication.UnicodeUTF8))
self.loadBtn.setText(QtGui.QApplication.translate("Form", "Load Example", None, QtGui.QApplication.UnicodeUTF8))
# -*- coding: utf-8 -*-
"""
In this example we draw two different kinds of histogram.
"""
import initExample ## Add path to library (just for examples; you do not need this)
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np