Can't write to QTextBrowser when calling function from another file - python

I have a python plugin where the main.py file displays a QTextBrowser and writes some text. This works fine.
I wrote a second file anotherFile.py which identifies the same QTextBrowser but cannot write any text to it. Perhaps it needs to take ownership, I'm not sure?
Here is the code used:
# main.py #
from Example_dockwidget import ExampleDockWidget
from anotherFile import anotherClass
class Example:
def __init__(self, iface):
self.iface = iface
def function(self):
self.dockwidget = ExampleDockWidget()
self.dockwidget.show()
textBrowser = self.dockwidget.textBrowser
#textBrowser.setText('This works!')
a = anotherClass(self)
a.anotherFunction()
# anotherFile.py #
from Example_dockwidget import ExampleDockWidget
class anotherClass:
def __init__(self, iface):
self.iface = iface
self.dockwidget = ExampleDockWidget()
def anotherFunction(self):
textBrowser = self.dockwidget.textBrowser
textBrowser.setText('This does not work!')
print 'Why?'
# Example_dockwidget.py #
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'Example_dockwidget_base.ui'))
class ExampleDockWidget(QtGui.QDockWidget, FORM_CLASS):
def __init__(self, parent=None):
super(ExampleDockWidget, self).__init__(parent)
self.setupUi(self)

Your two classes both create their own ExampleDockWidget. Only one of them is shown (has its show method called) but there are two.
So it's not surprising that text sent to one does not appear on the other. You need to arrange for your anotherClass object to obtain a reference to the other ExampleDockWidget so it can share the same one.

As strubbly mentioned, I need to reference the same ExampleDockWidget instead of creating separate versions. In the anotherFile.py file, I added an extra parameter to take in ExampleDockWidget:
class anotherClass:
def __init__(self, iface, dockwidget):
self.iface = iface
self.dockwidget = dockwidget
def anotherFunction(self):
textBrowser = self.dockwidget.textBrowser
textBrowser.setText('This does not work!')
print 'Why?'
And then inserted the reference in the main.py file:
def function(self):
self.dockwidget = ExampleDockWidget()
self.iface.addDockWidget(Qt.RightDockWidgetArea, self.dockwidget)
self.dockwidget.show()
textBrowser = self.dockwidget.textBrowser
#textBrowser.setText('This works!')
a = anotherClass(self.iface, self.dockwidget)
a.anotherFunction()

Related

Cant access custom widget instance when iterating through layout

I have a layout that I add a widget, class called ColList. When I run widget.children() I get an expected result, a list of widget. however when I try to run a method of ColList or access a variable pyqt crashes. For now I am trying to run a my sanity check method each ColList instance
I am using two .ui files. if you want me to post them I can. this is the (reduced) code I am trying to get to work
class ColList(QWidget):
def __init__(self, col, parent=None):
super().__init__(parent)
# Load the GUI
uic.loadUi("Listwidget.ui", self)
self.title = col
self.groupBox.setTitle(col)
print(self.parent())
def SC(self):
print("hi")
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
uic.loadUi("MainWindow.ui", self)
self.columns = ['a', 'b']
self.loadTags
def loadTags(self):
for i in self.columns:
# TagsH is the name of a Horizontal layout that is itself a child of a QScrollarea named scrollFilters
self.TagsH.insertWidget(self.TagsH.count() - 1, ColList(f"{i}", parent=self))
def applyFilters(self):
# the print works it outputs: [<PyQt6.QtWidgets.QWidget object at 0x00000221161E2830>, <PyQt6.QtWidgets.QWidget object at 0x00000221161E28C0>]
print(self.scrollFilters.children()[1:])
# this print outputs an empty list
print(self.TagsH.children())
for i in self.scrollFilters.children()[1:]:
# this part seems to crash the program
i.widget().SC()

How can I call a function inside a class?

I have a class in globals.py as:
#!/usr/bin/env python
class fg():
def red(text): return f'\033[00;49;031m{text}\033[0m'
def heading(text): return red(text)
and I have the testrun.py script as:
#!/usr/bin/env python
from globals import fg
# Command 1:
print(fg.red("My text"))
# prints as expected
# Command 2:
print(fg.heading("My text"))
# throws the error: NameError: name 'red' is not defined
The question is how can call red function within the heading function.
When calling member functions you have to use the self argument, and initiate the class. So the calls would be like this.
class fg():
def red(self, text):
return f'\033[00;49;031m{text}\033[0m'
def heading(self, text):
return self.red(text)
and then
print(fg().red("My text"))
# prints as expected
# Command 2:
print(fg().heading("My text"))
First, there is a typo in your code. You misspelled return as "retrun".
Also, you can't call a class method directly. Here is what you're probably looking for.
class fg():
def __init__(self, text):
self.text = text
def red(self):
return f'\033[00;49;031m{self.text}\033[0m'
def heading(self):
return self.red()
And now you can import the file.
from globals import fg
obj = fg("My text")
print(obj.red())
print(obj.heading())
I have made a lot of modifications to your code.
Use self to call the class methods
If the text parameter is the same for both, you need not pass it every time you call these methods. Instead, you can initialize that in the self method itself.
You first need to create an object of a class to access its methods (called constructors).
First you should have init function in a class to call the class, then you should create some functions. Then you can create some static function that can be called without passing the parameters of the Class.In Your globals.py file:
class Fg:
def __init__(self):
#You can place some code that you
#want to call when this class is called
self.text = ""
def red(self, text):
#The self.text will make the text usable by
# both the functions
self.text = text
#Return what ever you want
return f'\033[00;49;031m{text}\033[0m'
def heading(self, text):
self.text = text
return self.red()
In your testrun.py file:
from globals import Fg
print(Fg().red("Your Text"))
print(Fg().heighlight("Your Text"))

Calling variable in one class file to another file in python3

Hi I'm a newbie in python programming. Please help me with this problem in python3:
pack.py
class one:
def test(self):
number = 100 ######I want to access this value and how?
print('test')
class two:
def sample(self):
print('sample')
another.py
from pack import *
class three:
def four(self):
obj = one()
print(obj.test())
###### I want to access the number value in this file and i don't know how #######
obj = three()
obj.four()
Here is an alternative
pack.py
class One:
def __init__(self):
self.number = 100
def test(self):
print('test')
class Two:
def sample(self):
print('Sample')
another.py
from pack import *
class Three:
def four(self):
self.obj = One().number
return self.obj
three = Three().four()
print(three)
By what seems to be your approach, you were using classes to access variables. It is better to instantiate variables in a constructor ( init method in class One). Then import the class and access it in another class of another file.
Also, it is a good practice to name classes beginning with uppercase letters. There are more possible ways but hope it helps.
number needs to be in a global scope, that means outside of a function definition (it shouldn't be indented)
if the variable is inside a function it is impossible to get it in another file
pack.py
number = 100
def test():
test.other_number = 999 # here we assigne a variable to the function object.
print("test")
another.py
import pack
pack.test()
print(pack.number)
print(test.other_number) # this only works if the function has been called once
Alternatively if you are using classes:
pack.py
class Someclass():
other_number = 999 # here we define a class variable
def __init__(self):
self.number = 100 # here we set the number to be saved in the class
def test(self):
print(self.number) # here we print the number
another.py
import pack
somclass_instance = pack.Someclass() # we make a new instance of the class. this runs the code in __init__
somclass_instance.test() # here we call the test method of Someclass
print(somclass_instance.number) # and here we get the number
print(Someclass.other_number) # here we retrieve the class variable

Python - Inheritance

I'm not understanding any online documentation about how to make inheritance work.
I have this here:
import maya.cmds as cmds
class RigLegs():
def __init__(self, *args):
self.rigLegs()
def rigLegs(self):
self.items["side"] = "left"
self.lIK = cmds.duplicate(self.lJoints["hip"], n = self.getName("hip_IK"))
for i in self.lIK:
newName = i[0].replace("_JNT", "_IK")
cmds.rename(i, newName)
But it's complaining that there is no self.items - I have to inherit it from another class which is far too large to post here. Can anyone help me figure out how to do that? I've researched online and nothing makes any sense.
The other class is in a different file altogether.
To inherit from another class do:
class RigLegs(base_class_name):
An Example:
class base_class():
items = [1,2,3]
class pie(base_class):
def __init__(self):
print (self.items)
instance = pie()
You can read more in the Python Documentation
With imports:
file (apples.py)
class base():
items = [1,3,4]
file (main_file.py)
import apples
class pie(apples.base):
def __init__(self):
self.pies()
def pies(self):
print(self.items)
instance = pie()
In the class declaration: class RigLegs(), you should include all the classes you want to inherit from, such as in:
class RigLegs(Ancestor1, Ancestor2):
# Your code chere.
Don't forget that you still need to call the initialization logic of your ancestors.
def __init__(self):
super(RigLegs, self).__init__()

Creating subclass for wx.TextCtrl

I'm creating a subclass for the wx.TextCtrl in wxpython.
I want this class to add extra data to the wx.TextCtrl widgets similar as to the way extra data can be added to a ComboBox or ListBox.
Here's my code:
import wx
class ExtraDataForTxtCtrl(wx.TextCtrl):
def __init(self, ExtraTextData):
self.ExtraTextData=ExtraTextData
def getExtraTCData(self):
return self.ExtraTextData
def setExtraTCData(self, ExtraTextData):
self.ExtraTextData=ExtraTextData
My problem is that I'm new to python and have no idea how to implement this and if it is correct or not.
import wx
class ExtraDataForTxtCtrl(wx.TextCtrl):
def __init__(self,*args,**kwargs):
self.ExtraTextData=kwargs.pop("ExtraTextData")
wx.TextCtrl.__init__(self,*args,**kwargs)
def getExtraTCData(self):
return self.ExtraTextData
def setExtraTCData(self, ExtraTextData):
self.ExtraTextData=ExtraTextData
possibly a better solution would be to use set/getattr
class DataTxtCtrl(wx.TextCtrl):
def __init__(self,*args,**kwargs):
self.datadict = {}
self.ExtraTextData=kwargs.pop("ExtraTextData")
wx.TextCtrl.__init__(self,*args,**kwargs)
def __getattr__(self,attr):
return self.datadict[attr]
def __setattr__(self,attr,val):
self.datadict[attr]=val
then you can set many variables and use it like normal
a = wx.App(redirect=False)
f = wx.Dialog(None,-1,"Example")
te = DataTxtCtrl(f,-1,"some_default")
te.somevar = "hello"
te.someother = "world"
print te.somevar+" "+te.someothervar
f.ShowModal()
Instead of creating a subclass I just decided to create my own class which links an extra string value to wx.textCtrl widgets.
Thanks to all who contributed! :)
Heres my code:
class TextDataHolder:
def __init__(self, wxTextControl, data):
self.wxTextControl=wxTextControl
self.data=data
def setDataTxt(self,data):
self.wxTextControl=wxTextControl
self.data=data
def getDataTxt(self):
return self.data
Heres how I implemented it:
import wx, TextDataHolder
exampleCtrl=wx.TextCtrl(self, -1, "Hello")
exampleData=TextDataHolder.TextDataHolder(exampleCtrl,"Sup?")
print exampleData.getDataTxt() #prints 'Sup?'

Categories