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"...
Related
I am trying to figure out what instance variables do not show up in auto completion in an IPython or Jupyter notebook. For example, if I have the class below:
class A:
def __init__(self, var_a: int):
self.var_a = var_a
and I define a class B that takes an instance of A at initialization, it seems like autocompletion does not look through to the definition of class A to see that it has a var_a instance attribute.
class B:
def __init__(self, var_b: A):
self.var_b = var_b
def func(self):
self.var_b.
I do not get any type hints if I press tab after the last period in the snippet above. Pylance (through the VS Code Python extension) and PyCharm both show autocompletion for self.var_b.var_a. Is there a way to configure either IPython or the code annotations so that autocompletion will also work in IPython?
Using IPython 8.4.0
Tried %config Completer.use_jedi = True in the first notebook cell which did not help.
Explicitly annotating the namespaces of the classes should work:
class A:
var_a: int
def __init__(self, var_a: int) -> None:
self.var_a = var_a
class B:
var_b: A
def __init__(self, var_b: A) -> None:
self.var_b = var_b
It doesn't get more explicit than that. If this code doesn't lead to proper type inference/auto-suggestions, that should be considered a bug.
i originally made scripts with many functions on 2 individual scala worksheets. i got them working and now want to tie these individual scripts together by importing and using them into a third file. from what i have read you can not simply import external scripts you must first make them into a class and put them into a package. so i tried that but i still couldn't import it
i know this may be a bit basic for this site but im struggling to find much scala documentation.
i think my problem might span from a missunderstanding of how packages work. the picture below might help.
my program example
adder.scala
package adder
class adder {
def add_to_this(AA:Int):Int={
var BB = AA + 1;
return BB
}
}
build.scala
package builder
class build {
def make_numbers(){
var a = 0;
var b = 0;}
}
main.sc
import adder
import builder
object main {
adder.adder.add_to_this(10);
}
the errors i get are
object is not a member of package adder
object is not a member of package builder
Classes in scala slightly differ from classes in java. If you need something like singleton, you'll want to use object instead of class i.e.:
package com.example
object Main extends App {
object Hide{
object Adder{
def addToThis(AA:Int):Int = AA + 1
}
}
object Example{
import com.example.Main.Hide.Adder
def run(): Unit = println(Adder.addToThis(10))
}
Example.run()
}
Consider objects like packages/modules which are also regular values. You can import an object by its full path, i.e. com.example.Main.Hide.Adder you can also import contents of an object by adding .{addToThis}, or import anything from object by adding ._ after an object.
Note that classes, traits and case classes could not be used as objects, you can't do anything with it unless you have an instance - there are no static modifier.
I am trying to add Maccept method to the ImageDialog class and connect this to okButton. However when I compile this code it will give :
AttributeError: 'ImageDialog' object has no attribute 'Maccept'
But I have already defined Maccept method inside the class.
from PyQt5.QtWidgets import QDialog,QApplication
from ui_imagedialog import Ui_ImageDialog
import sys
class ImageDialog(QDialog):
def __init__(self):
super(ImageDialog, self).__init__()
# Set up the user interface from Designer.
self.ui = Ui_ImageDialog()
self.ui.setupUi(self)
# Make some local modifications.
#self.ui.colorDepthCombo.addItem("2 colors (1 bit per pixel)")
# Connect up the buttons.
self.ui.okButton.clicked.connect(self.Maccept())
self.ui.cancelButton.clicked.connect(self.reject)
def Maccept(self):
print 'accept'
def main():
app=QApplication(sys.argv)
window=ImageDialog()
window.show()
sys.exit(app.exec_())
if __name__=='__main__':
main()
it was a stupid mistake. i am using vi as an editor and it has auto indent feature apparently puts a tab character for the indentation. I replaced with 4xspace character and solved.
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):
...
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.