How to drag and drop into a QTableWidget? (PyQT) - drag-and-drop

I'm struggling with getting drag&drop to work. I want to be able to drag&drop from a QPushButton into a cell of a QTableView. I've looked at a few tutorials online but seem to be stuck at the first step. The example below is changed from the amazing zetcode tutorial:
http://zetcode.com/tutorials/pyqt4/dragdrop/
Using the code below, when I drag the button into tableWidget, the dragEnterEvent seems to be get called, but once I hover the mouse over the table, I get that symbol that I'm not allowed to drop over the table, so can never get to the drop event :(
I have to admit I'm fairly new to pyqt, so may be missing something very simple. Would really appreciate any help I could get!
Cheers
Dave
import sys
from PyQt4 import QtGui
from PyQt4 import QtCore
class Button(QtGui.QPushButton):
def __init__(self, title, parent):
super(Button, self).__init__(title, parent)
def mouseMoveEvent(self, e):
if e.buttons() != QtCore.Qt.RightButton:
return
mimeData = QtCore.QMimeData()
drag = QtGui.QDrag(self)
drag.setMimeData(mimeData)
drag.setHotSpot(e.pos() - self.rect().topLeft())
dropAction = drag.start(QtCore.Qt.MoveAction)
def mousePressEvent(self, e):
QtGui.QPushButton.mousePressEvent(self, e)
if e.button() == QtCore.Qt.LeftButton:
print 'press'
class MyTable(QtGui.QTableWidget):
def __init__(self, rows, columns, parent):
super(MyTable, self).__init__(rows, columns, parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
print e.accept()
def dropEvent(self, e):
print 'blah'
position = e.pos()
self.button.move(position)
e.setDropAction(QtCore.Qt.MoveAction)
e.accept()
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
self.setAcceptDrops(True)
self.button = Button('Button', self)
self.table = MyTable(2,2,self)
self.table.setAcceptDrops(True)
self.table.setDragEnabled(True)
self.setWindowTitle('Click or Move')
self.setGeometry(300, 300, 280, 150)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.button)
layout.addWidget(self.table)
self.setLayout(layout)
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
if __name__ == '__main__':
main()

Because you are setting up drag and drop on a QTableWidget, you also need to re-implement it's dragMoveEvent. As per the docs here:
Subclassing Complex Widgets
Certain standard Qt widgets provide their
own support for drag and drop. When subclassing these widgets, it may
be necessary to reimplement dragMoveEvent() in addition to
dragEnterEvent() and dropEvent() to prevent the base class from
providing default drag and drop handling, and to handle any special
cases you are interested in.
class MyTable(QtGui.QTableWidget):
...
def dragMoveEvent(self, e):
e.accept()
Also, be aware that while the original tutorial shows how to move a button within a widget without any layouts, your example now has the button managed by a vertical layout. So your self.button.move(position) will not work as expected. Though the dropEvent should fire properly and you should be getting the "accepted" drag icon when it hovers a cell.

Related

In Scala, how can I use implicit conversion to "add" methods to subclasses of a common parent?

Let's say I have some data in "dumb" models. In this example, I'll use Circle and Triangle, which extend a trait Shape.
I'm looking for a way to isolate behavior that could use these shapes, but I'm not sure the best way to structure it. If I'm trying to draw these shapes onto a document, I'd want to be able to write code that looked like this:
shapes.foreach(doc.add)
The trick here is that shapes is Seq[Shape], and the add method is something I want to add implicitly since I can't modify the shapes themselves (nor would I want to bake this specific functionality into them).
Where I'm getting stuck is, I don't know how to mix implicit conversions with the subclasses. See QUESTION: below in the code for more info.
// Let's assume I'm working with some shape models that are defined in some
// external library that's out of my control.
sealed trait Shape
case class Circle() extends Shape
case class Triangle() extends Shape
// Now I'm building an add that adds stuff to a Document
// and I want to locally implement methods that work on these general shapes.
case class Document()
// Using implicit conversion to add methods to a case class that's just holding data
implicit class DocumentExtensions(doc: Document) {
// I don't want this to be called
def add(shape: Shape): Unit = println("Add a shape")
// I want to use shape-specific methods
def add(shape: Circle): Unit = println("Add a circle")
def add(shape: Triangle): Unit = println("Add a triangle")
}
val doc = Document()
val shapes = Seq(Circle(), Triangle())
// This just prints "Add a shape" for the Circle and Triangle.
// I want to it to print "Add a circle" and "Add a triangle".
shapes.foreach { shape =>
// QUESTION:
// Is there a way or pattern to have this call the add for the
// subclass instead of for Shape? I want this to be fully dynamic
// so that I don't have to list out each subclass. Even more ideally,
// the compiler could warn me if there was a subclass that there wasn't
// an implicit add for.
doc.add(shape)
}
// This would work, but I'm wondering if there's a way to do this more
// dynamically without listing everything out.
shapes.foreach {
case c: Circle => doc.add(c)
case t: Triangle => doc.add(t)
}
I'm sure there's a name for what I'm looking for, but I just don't know what it is or what to search for.
Problem: compiler cannot choose and use an implicit value specific to handle a subclass. It's basically impossible to decide what method to call (for Triangle or Circle) when you only know that it's a Shape. This is actually a classical problem, which has standard solutions.
Solution 1
Pattern matching inside DocumentExtension.add
Pros:
Since your trait Shape is defined as sealed, compiler will you if you miss a case for a certain ancestor.
Separation of class definition and action handling
Cons:
Boilerplate required to list all subclasses of your trait
Solution 2
Classical Visitor pattern
sealed trait Shape {
def addToDoc(doc: Document, visitor: ShapeDrawer)
}
final class Triangle extends Shape {
def addToDoc(doc: Document, visitor: ShapeDrawer) = visitor.draw(doc, this)
}
final class Circle extends Shape {
def addToDoc(doc: Document, visitor: ShapeDrawer) = visitor.draw(doc, this)
}
trait ShapeDrawer {
def draw(doc: Document, t: Circle)
def draw(doc: Document, t: Triangle)
}
val drawer: ShapeDrawer = ???
val doc: Document = ???
val shapes = Seq.empty[Shape]
shapes.foreach(_.addToDoc(doc, drawer))
This solution also matches the requirement of being sure at compile time that you've handled every subclass of Shape, but requires adding strange methods to the trait itself.

Splitting python class into multiple files

I wondered if anyone could tell me is it possible to divide the following code into two python classes which will then be placed in two different files:
from GUI import mainGUI
from GUI import subwindowGUI
class MyApp(QMainWindow, mainGUI.Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
# mainGUI contains QMdiarea in which it opens
# a subwindow by calling a function MySubWin(self)
# QMdiarea name is 'body'
self.OpenSub.triggered.connect(self.MySubWin)
def MySubWin(self):
self.MySubWin = QWidget()
self.MySubWin.setObjectName('Module window')
self.myTabs = QtabWidget(self.MySubWin)
self.myTabs.setObjectName('myTabs')
# now I call the function that will display
# the gui elements inside this 'Module window'
self.create_module_gui()
self.body.addSubWindow(self.MySubWin)
self.MySubWin.showNormal()
def create_module_gui(self, *args):
module_gui = subwindowGUI.Ui_ModuleWindow()
module_gui.setupUi(module_gui)
self.myTabs.addTab(module_gui, _('New tab'))
self.myTabs.setCurrentWidget(module_gui)
As you can see from the code above my functions are interacting with the main window gui elements. I wanted to move these functions that are related to this specific module into a separate file for the maintaining purposes. That's why I'm asking you to help me on how to achieve that if it's even possible. Thanks in advance, Tomislav.
#Mel:
If I for move those functions into another file:
myFunctions.py
class MyFunctions(object):
def MySubWin(self):
self.MySubWin = QWidget()
self.MySubWin.setObjectName('Module window')
self.myTabs = QtabWidget(self.MySubWin)
self.myTabs.setObjectName('myTabs')
# now I call the function that will display
# the gui elements inside this 'Module window'
self.create_module_gui()
self.body.addSubWindow(self.MySubWin)
self.MySubWin.showNormal()
def create_module_gui(self, *args):
module_gui = subwindowGUI.Ui_ModuleWindow()
module_gui.setupUi(module_gui)
self.myTabs.addTab(module_gui, _('New tab'))
self.myTabs.setCurrentWidget(module_gui)
and then I import that file into my main file.
import myFunctions
class MyApp(QMainWindow, mainGUI.Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
# mainGUI contains QMdiarea in which it opens
# a subwindow by calling a function MySubWin(self)
# QMdiarea name is 'body'
self.OpenSub.triggered.connect(MyFunctions.MySubWin)
What I end up with is the error saying that MyFunctions object has no attribute body.
1st I must say that you won't gain any maintenance out of this ... but for example lets move the create_module_gui to another class
in a new file: creategui.py
class CreateGUI(object):
def create_module_gui(self, *args):
module_gui = subwindowGUI.Ui_ModuleWindow()
module_gui.setupUi(module_gui)
self.myTabs.addTab(module_gui, _('New tab'))
self.myTabs.setCurrentWidget(module_gui)
in your code:
from GUI import mainGUI
from GUI import subwindowGUI
from creategui import CreateGUI
class MyApp(QMainWindow, mainGUI.Ui_MainWindow, CreateGUI):
#yay you have your create_module_gui method now...
Now you can also just put create_module_gui as a function in another file and call it with self as the first param...
See this solution: https://stackoverflow.com/a/47562412/10155767
In your case, don't make a class in myFunctions.py. Instead, define the functions at the top level. Thus myFunctions.py should look like:
def MySubWin(self):
...
def create_module_gui(self, *args):
...
Then in your original file, import the functions within the class like
class MyApp(QMainWindow, mainGUI.Ui_MainWindow):
from myFunctions import MySubWin, create_module_gui
def __init__(self, parent=None):
...

Display encapsulated widget in IPython notebook

I have an object that encapsulates a widget.
class Foo(object):
def __init__(self, widget):
self.widget = widget
I want this object to display itself as this widget in the notebook.
>>> my_widget
<fancy widget>
>>> Foo(my_widget)
<fancy widget>
Is there a method that I should implement on my Foo class to accomplish this?
ipywidgets piggy backs onto IPython's rich display system. _ipython_display_ is a hook in the system that allows you to intercept display calls. Try the following:
class Foo(object):
def __init__(self, widget):
self.widget = widget
def _ipython_display_(self, **kwargs):
self.widget._ipython_display_(**kwargs)
Cheers,
Jon
Edit: Here's the relevant example file included with ipython. Scroll down to "More complex display"...

ScalaFx Bind ImageView to custom Enumeration

I just started to write scalafx application and have a question about bindings.
I have an Enumeration with connection status in my presenter class and I want to select appropriate icon in label in view class. I basically can create binding in javafx way and set converter which will select appropriate ImageView every time status changes, but is it possible to do in ScalaFX way?
I looked many scalafx examples, but still can't find anything like this.
Here is some code:
package view
import scalafx.beans.property.ObjectProperty
class MainWindowPresenter {
object DatabaseState extends Enumeration {
type DatabaseState = Value
val NOT_CONNECTED, IDLE, BUSY, ERROR = Value
}
val login = new ObjectProperty[String](this, "login", "awesomeloginname")
val state = new ObjectProperty[DatabaseState.DatabaseState](this, "state", DatabaseState.ERROR)
}
View class:
package view
import java.util.concurrent.Callable
import javafx.beans.binding.ObjectBinding
import collection.immutable.HashMap
import javafx.scene.control.SeparatorMenuItem
import scala.util.Random
import scalafx.beans.property.{ObjectProperty}
import scalafx.geometry.{Orientation, Insets, Pos}
import scalafx.scene.control._
import scalafx.scene.image.{ImageView, Image}
import scalafx.scene.layout._
import scalafx.Includes._
class MainWindowView extends BorderPane {
val model = new MainWindowPresenter
top = new HBox {
content = List(
new Label() {
graphic <== //somehow select imageview depending on model.state
}
)
}
private def imageFromResource(name : String) =
new ImageView(new Image(getClass.getClassLoader.getResourceAsStream(name)))
}
Thanks in advance and sorry for grammar mistakes, if any - English isn't my native.
You can use EasyBind or the snapshot (2.0-SNAPSHOT) version of ReactFX to create the binding. Both are Java libraries, but they are easy to use from Scala. This is the EasyBind way:
graphic <== EasyBind.map(model.state, stateToImage)
val stateToImage: Function1[DatabaseState.DatabaseState, ImageView] = {
// convert state to ImageView
}
This code uses the implicit conversion from Scala's Function1 to Java's Function.
You could also define an implicit conversion from ScalaFX ObjectProperty to EasyBind's MonadicObservableValue and then the first line above can be rewritten to:
graphic <== model.state.map(stateToImage)

Base Class constructor not being called in JFXApp

package pGrid
package pUIFx
import pUtil._
object DevAppFx extends AppFx
{
println("Begining DevFxApp object constructor in package pGrid.pUIFx")
//devStart
}
package pGrid
package pUIFx
import pGeom._
import pGrid.pDev._
import scalafx.application._
import scalafx.application.JFXApp._
import scalafx.scene._
import scalafx.scene.paint._
class AppFx extends JFXApp with DevTr
{
println("Creating stage")
stage = new PrimaryStage
{
x = 3850
y = 200
width = 1000
height = 800
scene = new Scene
}
def openEFO(de: DescEFlatOne): Unit =
{
println("def in AppFx")
stage.scene = ScrEditFx(stage, de)
}
}
The DevAppFx object constructor runs, including the println ("Beginning ...
The class AppFx constructor does not run including the println ("creating stage"). The openEFO method can be called but the stage variable is null.
Edit this is a simplification. There will be a lot more functionality in DEVAppFx and AppFx, so its important to be able to keep the functionality separate.
I think the issue here is that scalafx.application.JXFApp is a class that extends the scala.DelayedInit trait. As such, some Scala magic happens under the hood: see the scala.DelayedInit docs for more. Unfortunately, DelayedInit is buggy and plays havoc with sub-class initialization/construction code - such as your AppFx class not executing its constructor.
There's no easy solution to this, I'm afraid. Until the DelayedInit behavior is resolved, or until we find a better way to initialize ScalaFX, your best bet is to merge DevAppFx and AppFx into a single object, which should work as expected.
For example:
package pGrid
package pUIFx
import pGeom._
import pGrid.pDev._
import scalafx.application._
import scalafx.application.JFXApp._
import scalafx.scene._
import scalafx.scene.paint._
object AppFx extends JFXApp with DevTr
{
println("Creating stage")
stage = new PrimaryStage
{
x = 3850
y = 200
width = 1000
height = 800
scene = new Scene
}
// Relocate DevAppFx init here...
println("Begining DevFxApp object constructor in package pGrid.pUIFx")
//devStart
def openEFO(de: DescEFlatOne): Unit =
{
println("def in AppFx")
stage.scene = ScrEditFx(stage, de)
}
}
UPDATE:
I did some more digging around, and scalafx.application.JFXApp didn't do a great job of implementing the semantics of the scala.DelayedInit trait. In essence, it was only storing the construction/initialization code of the class/object at the bottom of the inheritance hierarchy, and dropping everything else. For further details, there is a ScalaFX bug report for this issue.
So, in your example, the construction code for the object DevAppFx was replacing the construction code for your class AppFx, instead of storing both, resulting in the symptoms you observed.
I've committed a patch to the default and SFX-8 branches of ScalaFX on Google Code, which you're free to utilize. Alternatively, if you're prepared to wait a few weeks, the next updates published to the Sonatype OSS to have the patch will be 1.0.0-R9 (for the JavaFX 2 equivalent) and 8.0.0-R5 (for the JavaFX 8 equivalent).
This patch should allow your original code to run unmodified. If you get a chance to try it out, let me know how you get on...
I've use the information about possible bugs in DelayedInit from Mike Allen's answer. However I want to keep the functionality separate rather than combining it into one object. Reading the docs, the problem is with classes and Objects not with traits that inherit from JFXApp and DelayedInit, so I have converted AppFx into a trait and moved the Stage creation into a method
object DevAppFx extends AppFx with DevTr
{
openStage
devStart
}
____________--
trait AppFx extends JFXApp with StratApp
{
def openStage: Unit = stage = new PrimaryStage
{
x = 3850
y = 200
width = 1000
height = 800
scene = new Scene
}
override def openEFO(de: DescEFlatOne): Unit = stage.scene = ScrEditFx(this, de)
}