Help Assigning Spinbox setting to value
-
wrote on 25 Jan 2024, 10:44 last edited by Laurie49
This is my first attempt at anything using Python so apologies for any incorrect terminology.
I am trying to produce a macro in the 3D modelling programme FreeCAD.
I want to highlight the vertexes at a specified location (“Depth”) along any specified axis (“Position”) on my 3D model (see cube image below)
If I change the “Depth” value in the Spinbox it will highlight the vertexes in accordance with the change in the slot. However this will not work when changing the “Position” value. I have to change the axis in the code to produce the desired result.
I would appreciate any advice and help to get the Spinbox working properly.``` from PySide.QtGui import * class VertexSelector(QWidget): def __init__(self): super(VertexSelector, self).__init__() ##vars self.depth = 10.0 self.position = 0 #X=0,Y=1,Z=2 #See comment line 44 about variable ##Depth object self.lblDepth = QLabel("Depth:") self.sbDepth = QDoubleSpinBox() self.sbDepth.setValue(self.depth) self.sbDepth.setSingleStep(0.5) self.lblPosition = QLabel("Position:") self.sbPosition = QDoubleSpinBox() self.sbPosition.setValue(self.position) self.sbPosition.setSingleStep(1) ##button self.btnApply = QPushButton("Apply") self.btnApply.clicked.connect(self.apply) #layout layout = QVBoxLayout() layout.addWidget(self.lblDepth) layout.addWidget(self.sbDepth) layout.addWidget(self.lblPosition) layout.addWidget(self.sbPosition) layout.addWidget(self.btnApply) self.setLayout(layout) ##window self.setWindowFlags(Qt.WindowStaysOnTopHint) self.show() def apply(self): self.depth = float(self.sbDepth.value()) self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present shapes = App.ActiveDocument.findObjects("Part::Feature") for sh in shapes: vertexes = [] vertexCount = len(sh.Shape.Vertexes) for vertexIdx in range(vertexCount): try: position = sh.Shape.Vertexes[vertexIdx].Point vertexName="Vertex"+str(vertexIdx+1) App.Console.PrintMessage(vertexName+":") App.Console.PrintMessage(str(round(position[0],2))) #This is the setting that defines the axis - I want to make this variable if (round(position[0],2) == self.depth): vertexes.append(vertexName) App.Console.PrintMessage("\n") except Exception: App.Console.PrintMessage("Not applicable\n") Gui.Selection.addSelection(sh,vertexes) fselector = VertexSelector() ```  image url)
-
This is my first attempt at anything using Python so apologies for any incorrect terminology.
I am trying to produce a macro in the 3D modelling programme FreeCAD.
I want to highlight the vertexes at a specified location (“Depth”) along any specified axis (“Position”) on my 3D model (see cube image below)
If I change the “Depth” value in the Spinbox it will highlight the vertexes in accordance with the change in the slot. However this will not work when changing the “Position” value. I have to change the axis in the code to produce the desired result.
I would appreciate any advice and help to get the Spinbox working properly.``` from PySide.QtGui import * class VertexSelector(QWidget): def __init__(self): super(VertexSelector, self).__init__() ##vars self.depth = 10.0 self.position = 0 #X=0,Y=1,Z=2 #See comment line 44 about variable ##Depth object self.lblDepth = QLabel("Depth:") self.sbDepth = QDoubleSpinBox() self.sbDepth.setValue(self.depth) self.sbDepth.setSingleStep(0.5) self.lblPosition = QLabel("Position:") self.sbPosition = QDoubleSpinBox() self.sbPosition.setValue(self.position) self.sbPosition.setSingleStep(1) ##button self.btnApply = QPushButton("Apply") self.btnApply.clicked.connect(self.apply) #layout layout = QVBoxLayout() layout.addWidget(self.lblDepth) layout.addWidget(self.sbDepth) layout.addWidget(self.lblPosition) layout.addWidget(self.sbPosition) layout.addWidget(self.btnApply) self.setLayout(layout) ##window self.setWindowFlags(Qt.WindowStaysOnTopHint) self.show() def apply(self): self.depth = float(self.sbDepth.value()) self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present shapes = App.ActiveDocument.findObjects("Part::Feature") for sh in shapes: vertexes = [] vertexCount = len(sh.Shape.Vertexes) for vertexIdx in range(vertexCount): try: position = sh.Shape.Vertexes[vertexIdx].Point vertexName="Vertex"+str(vertexIdx+1) App.Console.PrintMessage(vertexName+":") App.Console.PrintMessage(str(round(position[0],2))) #This is the setting that defines the axis - I want to make this variable if (round(position[0],2) == self.depth): vertexes.append(vertexName) App.Console.PrintMessage("\n") except Exception: App.Console.PrintMessage("Not applicable\n") Gui.Selection.addSelection(sh,vertexes) fselector = VertexSelector() ```  image url)
-
This is my first attempt at anything using Python so apologies for any incorrect terminology.
I am trying to produce a macro in the 3D modelling programme FreeCAD.
I want to highlight the vertexes at a specified location (“Depth”) along any specified axis (“Position”) on my 3D model (see cube image below)
If I change the “Depth” value in the Spinbox it will highlight the vertexes in accordance with the change in the slot. However this will not work when changing the “Position” value. I have to change the axis in the code to produce the desired result.
I would appreciate any advice and help to get the Spinbox working properly.``` from PySide.QtGui import * class VertexSelector(QWidget): def __init__(self): super(VertexSelector, self).__init__() ##vars self.depth = 10.0 self.position = 0 #X=0,Y=1,Z=2 #See comment line 44 about variable ##Depth object self.lblDepth = QLabel("Depth:") self.sbDepth = QDoubleSpinBox() self.sbDepth.setValue(self.depth) self.sbDepth.setSingleStep(0.5) self.lblPosition = QLabel("Position:") self.sbPosition = QDoubleSpinBox() self.sbPosition.setValue(self.position) self.sbPosition.setSingleStep(1) ##button self.btnApply = QPushButton("Apply") self.btnApply.clicked.connect(self.apply) #layout layout = QVBoxLayout() layout.addWidget(self.lblDepth) layout.addWidget(self.sbDepth) layout.addWidget(self.lblPosition) layout.addWidget(self.sbPosition) layout.addWidget(self.btnApply) self.setLayout(layout) ##window self.setWindowFlags(Qt.WindowStaysOnTopHint) self.show() def apply(self): self.depth = float(self.sbDepth.value()) self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present shapes = App.ActiveDocument.findObjects("Part::Feature") for sh in shapes: vertexes = [] vertexCount = len(sh.Shape.Vertexes) for vertexIdx in range(vertexCount): try: position = sh.Shape.Vertexes[vertexIdx].Point vertexName="Vertex"+str(vertexIdx+1) App.Console.PrintMessage(vertexName+":") App.Console.PrintMessage(str(round(position[0],2))) #This is the setting that defines the axis - I want to make this variable if (round(position[0],2) == self.depth): vertexes.append(vertexName) App.Console.PrintMessage("\n") except Exception: App.Console.PrintMessage("Not applicable\n") Gui.Selection.addSelection(sh,vertexes) fselector = VertexSelector() ```  image url)
wrote on 25 Jan 2024, 14:04 last edited by JonB@Laurie49 said in Help Assigning Spinbox setting to value:
self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present
Then there are two possibilities:
self.position
does not do what you want/expect it to do with a certain value; orfloat(self.sbPosition.value())
does not return the value you need/expect it to.
Which is it? Try first typing in (in code) a fixed value for
self.position
, then you will know whether it's that versus your title of "Help Assigning Spinbox setting to value". [So far as I can see you do nothing withself.position
after assigning to it.] -
@Laurie49 said in Help Assigning Spinbox setting to value:
self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present
Then there are two possibilities:
self.position
does not do what you want/expect it to do with a certain value; orfloat(self.sbPosition.value())
does not return the value you need/expect it to.
Which is it? Try first typing in (in code) a fixed value for
self.position
, then you will know whether it's that versus your title of "Help Assigning Spinbox setting to value". [So far as I can see you do nothing withself.position
after assigning to it.]wrote on 26 Jan 2024, 06:00 last edited by@JonB - Thank you for your response and advice.
I changed the value of self.position to 1 in the code and ran the macro.
The spin box opened with Position 1, and the depth at 10 (the cube is (10 by 10 by 10).
When I clicked the Apply button only the vertexes on the position setting on line 45 will will be highlighted even when I change the position number in the spin box.
So it appears to me that:-
The spin box Depth setting works as expected - it will pick up the vertexes at the bottom of the four cylinders, or single cylinder, or single cube pockets on their relevant position - but subject to the setting for the position on line 45. In other words the only way to change the position is to change the setting on line 45 - changing it in the spin box has no effect.[Only Altering Position number (0, 1, or 2) will change the axis will change the axis result.
I hope I have articulated this clearly. I have also uploaded some more screenshots in the hope that they will provide further clarification -
@JonB - Thank you for your response and advice.
I changed the value of self.position to 1 in the code and ran the macro.
The spin box opened with Position 1, and the depth at 10 (the cube is (10 by 10 by 10).
When I clicked the Apply button only the vertexes on the position setting on line 45 will will be highlighted even when I change the position number in the spin box.
So it appears to me that:-
The spin box Depth setting works as expected - it will pick up the vertexes at the bottom of the four cylinders, or single cylinder, or single cube pockets on their relevant position - but subject to the setting for the position on line 45. In other words the only way to change the position is to change the setting on line 45 - changing it in the spin box has no effect.[Only Altering Position number (0, 1, or 2) will change the axis will change the axis result.
I hope I have articulated this clearly. I have also uploaded some more screenshots in the hope that they will provide further clarification -
wrote on 26 Jan 2024, 08:27 last edited by
@Laurie49
Hi. You show a couple of very pretty/complicated screenshots, plus lots of code, which as a picture I find hard to read and cannot copy/paste from, always better as code!Take a step back for moment.
QSpinBox
es work. All you should be doing isprint(self.sbPosition.value())
to verify it returns whatever you expect it to from whatever you do to it on-screen. All the rest of the code is irrelevant to your claim that "the spinbox does not return the right value", and just complicates. You may have a fault in your logic as you what you do/do not do with the value, but that's not the question.I say again what I said before. In function
apply()
afterself.depth = float(self.sbDepth.value())
I do see you referenceself.depth
inif (round(position[0],2) == self.depth)
. However, afterself.position = float(self.sbPosition.value()) #This line soesn't impact the result at present
I do not see you referenceself.position
anywhere. In that comparison line you useposition
, which is a local variable set earlier viaposition = sh.Shape.Vertexes[vertexIdx].Point
, but neverself.positon
. So until your code actually uses the result from the spinbox value it won't have any effect.... That's all I know. -
@Laurie49
Hi. You show a couple of very pretty/complicated screenshots, plus lots of code, which as a picture I find hard to read and cannot copy/paste from, always better as code!Take a step back for moment.
QSpinBox
es work. All you should be doing isprint(self.sbPosition.value())
to verify it returns whatever you expect it to from whatever you do to it on-screen. All the rest of the code is irrelevant to your claim that "the spinbox does not return the right value", and just complicates. You may have a fault in your logic as you what you do/do not do with the value, but that's not the question.I say again what I said before. In function
apply()
afterself.depth = float(self.sbDepth.value())
I do see you referenceself.depth
inif (round(position[0],2) == self.depth)
. However, afterself.position = float(self.sbPosition.value()) #This line soesn't impact the result at present
I do not see you referenceself.position
anywhere. In that comparison line you useposition
, which is a local variable set earlier viaposition = sh.Shape.Vertexes[vertexIdx].Point
, but neverself.positon
. So until your code actually uses the result from the spinbox value it won't have any effect.... That's all I know. -
@JonB - thanks again. I am on a tablet at present but will change “position” to “self.position” on that line, see if that produces the desired outcome, and post accordingly.
wrote on 26 Jan 2024, 11:26 last edited by@Laurie49
Well it won't, because that line assigns toposition
/self.position
unconditionally. So it won't use what was read from the spinbox. I say once again, and for the last time, that if you don't use the result from the combobox's value anywhere it won't have any effect.... -
@Laurie49
Well it won't, because that line assigns toposition
/self.position
unconditionally. So it won't use what was read from the spinbox. I say once again, and for the last time, that if you don't use the result from the combobox's value anywhere it won't have any effect....wrote on 27 Jan 2024, 04:30 last edited by@JonB said in Help Assigning Spinbox setting to value:
@Laurie49
Well it won't, because that line assigns toposition
/self.position
unconditionally. So it won't use what was read from the spinbox. I say once again, and for the last time, that if you don't use the result from the combobox's value anywhere it won't have any effect....JohnB, I sincerely regret having taxed your patience. I would follow you advice if I could but the truth of the matter is I just don't know how to. That is not to say I have not tried - I have spent the last four hours trying to do so.
The nearest I have ever come to attempting something like this was in a spreadsheet where I would nest "If" statements. For example:
On the line that says :- if (round(position**[2]**,2) == self.depth):Putting aside the rounding I would attempt something like this:-
=IF(self.position=0,0,(IF(self.position=1,1,2)))Is this the correct sort of approach or am I way off track? Either way this novice would like to see how it is done.
I have inserted my macro code again belowfrom PySide.QtGui import * class VertexSelector(QWidget): def __init__(self): super(VertexSelector, self).__init__() ##vars self.depth = 10 self.position = 1 #X=0,Y=1,Z=2 #See comment line 45 about variable ##Depth object self.lblDepth = QLabel("Depth:") self.sbDepth = QDoubleSpinBox() self.sbDepth.setValue(self.depth) self.sbDepth.setSingleStep(0.5) self.lblPosition = QLabel("Position:") self.sbPosition = QSpinBox() self.sbPosition.setValue(self.position) self.sbPosition.setSingleStep(1) ##button self.btnApply = QPushButton("Apply") self.btnApply.clicked.connect(self.apply) #layout layout = QVBoxLayout() layout.addWidget(self.lblDepth) layout.addWidget(self.sbDepth) layout.addWidget(self.lblPosition) layout.addWidget(self.sbPosition) layout.addWidget(self.btnApply) self.setLayout(layout) ##window self.setWindowFlags(Qt.WindowStaysOnTopHint) self.show() def apply(self): self.depth = float(self.sbDepth.value()) self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present shapes = App.ActiveDocument.findObjects("Part::Feature") for sh in shapes: vertexes = [] vertexCount = len(sh.Shape.Vertexes) for vertexIdx in range(vertexCount): try: position = sh.Shape.Vertexes[vertexIdx].Point vertexName="Vertex"+str(vertexIdx+1) App.Console.PrintMessage(vertexName+":") App.Console.PrintMessage(str(round(position[0],2))) if (round(position[2],2) == self.depth):#It seems that this line is the only one that defines the position displayed. vertexes.append(vertexName) App.Console.PrintMessage("\n") except Exception: App.Console.PrintMessage("Not applicable\n") Gui.Selection.addSelection(sh,vertexes) fselector = VertexSelector()
-
@JonB said in Help Assigning Spinbox setting to value:
@Laurie49
Well it won't, because that line assigns toposition
/self.position
unconditionally. So it won't use what was read from the spinbox. I say once again, and for the last time, that if you don't use the result from the combobox's value anywhere it won't have any effect....JohnB, I sincerely regret having taxed your patience. I would follow you advice if I could but the truth of the matter is I just don't know how to. That is not to say I have not tried - I have spent the last four hours trying to do so.
The nearest I have ever come to attempting something like this was in a spreadsheet where I would nest "If" statements. For example:
On the line that says :- if (round(position**[2]**,2) == self.depth):Putting aside the rounding I would attempt something like this:-
=IF(self.position=0,0,(IF(self.position=1,1,2)))Is this the correct sort of approach or am I way off track? Either way this novice would like to see how it is done.
I have inserted my macro code again belowfrom PySide.QtGui import * class VertexSelector(QWidget): def __init__(self): super(VertexSelector, self).__init__() ##vars self.depth = 10 self.position = 1 #X=0,Y=1,Z=2 #See comment line 45 about variable ##Depth object self.lblDepth = QLabel("Depth:") self.sbDepth = QDoubleSpinBox() self.sbDepth.setValue(self.depth) self.sbDepth.setSingleStep(0.5) self.lblPosition = QLabel("Position:") self.sbPosition = QSpinBox() self.sbPosition.setValue(self.position) self.sbPosition.setSingleStep(1) ##button self.btnApply = QPushButton("Apply") self.btnApply.clicked.connect(self.apply) #layout layout = QVBoxLayout() layout.addWidget(self.lblDepth) layout.addWidget(self.sbDepth) layout.addWidget(self.lblPosition) layout.addWidget(self.sbPosition) layout.addWidget(self.btnApply) self.setLayout(layout) ##window self.setWindowFlags(Qt.WindowStaysOnTopHint) self.show() def apply(self): self.depth = float(self.sbDepth.value()) self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present shapes = App.ActiveDocument.findObjects("Part::Feature") for sh in shapes: vertexes = [] vertexCount = len(sh.Shape.Vertexes) for vertexIdx in range(vertexCount): try: position = sh.Shape.Vertexes[vertexIdx].Point vertexName="Vertex"+str(vertexIdx+1) App.Console.PrintMessage(vertexName+":") App.Console.PrintMessage(str(round(position[0],2))) if (round(position[2],2) == self.depth):#It seems that this line is the only one that defines the position displayed. vertexes.append(vertexName) App.Console.PrintMessage("\n") except Exception: App.Console.PrintMessage("Not applicable\n") Gui.Selection.addSelection(sh,vertexes) fselector = VertexSelector()
wrote on 27 Jan 2024, 12:47 last edited by JonB@Laurie49
I don't know what to say any more. At least (unlike some!) you are a nice, polite guy, so I am trying to be patient/not too hard on you :)Can you just look at your code and the following 3 lines. I want you to absorb the logic of what's going on:
self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present position = sh.Shape.Vertexes[vertexIdx].Point if (round(position[2],2) == self.depth):#It seems that this line is the only one that defines the position displayed.
- Line #1 is the only place you read the spinbox value. And you assign it to
self.position
. - Line #2 you read something from vertex point. I don't care what it is. You assign that to a local variable named
position
(which, btw, has nothing to do withself.position
in Python. - Line #3 is the only place you *read and use" the "position". And you do that from the
position
local variable assigned in Line #2.
Now, forget Python, forget anything else. You tell me where your calculations "logically" use the value read from the spinbox and assigned into
self.position
? They do not, anywhere. So as long as that is the case, how can what the user moves the spinbox value have any effect? It cannot.I don't know what you are reading from, what the correct formula is, but you need to revisit this. You simply throw away what is the spinbox and use only
position = sh.Shape.Vertexes[vertexIdx].Point
for your calculation. One of these is wrong.Finally, if you are asking how to translate
=IF(self.position=0,0,(IF(self.position=1,1,2)))
into Python that would be:
value = 0 if self.position == 0 else 1 if self.position == 1 else 2
and then you must use
value
somewhere. - Line #1 is the only place you read the spinbox value. And you assign it to
-
@Laurie49
I don't know what to say any more. At least (unlike some!) you are a nice, polite guy, so I am trying to be patient/not too hard on you :)Can you just look at your code and the following 3 lines. I want you to absorb the logic of what's going on:
self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present position = sh.Shape.Vertexes[vertexIdx].Point if (round(position[2],2) == self.depth):#It seems that this line is the only one that defines the position displayed.
- Line #1 is the only place you read the spinbox value. And you assign it to
self.position
. - Line #2 you read something from vertex point. I don't care what it is. You assign that to a local variable named
position
(which, btw, has nothing to do withself.position
in Python. - Line #3 is the only place you *read and use" the "position". And you do that from the
position
local variable assigned in Line #2.
Now, forget Python, forget anything else. You tell me where your calculations "logically" use the value read from the spinbox and assigned into
self.position
? They do not, anywhere. So as long as that is the case, how can what the user moves the spinbox value have any effect? It cannot.I don't know what you are reading from, what the correct formula is, but you need to revisit this. You simply throw away what is the spinbox and use only
position = sh.Shape.Vertexes[vertexIdx].Point
for your calculation. One of these is wrong.Finally, if you are asking how to translate
=IF(self.position=0,0,(IF(self.position=1,1,2)))
into Python that would be:
value = 0 if self.position == 0 else 1 if self.position == 1 else 2
and then you must use
value
somewhere. - Line #1 is the only place you read the spinbox value. And you assign it to
-
@Laurie49
I don't know what to say any more. At least (unlike some!) you are a nice, polite guy, so I am trying to be patient/not too hard on you :)Can you just look at your code and the following 3 lines. I want you to absorb the logic of what's going on:
self.position = float(self.sbPosition.value()) #This line soesn't impact the result at present position = sh.Shape.Vertexes[vertexIdx].Point if (round(position[2],2) == self.depth):#It seems that this line is the only one that defines the position displayed.
- Line #1 is the only place you read the spinbox value. And you assign it to
self.position
. - Line #2 you read something from vertex point. I don't care what it is. You assign that to a local variable named
position
(which, btw, has nothing to do withself.position
in Python. - Line #3 is the only place you *read and use" the "position". And you do that from the
position
local variable assigned in Line #2.
Now, forget Python, forget anything else. You tell me where your calculations "logically" use the value read from the spinbox and assigned into
self.position
? They do not, anywhere. So as long as that is the case, how can what the user moves the spinbox value have any effect? It cannot.I don't know what you are reading from, what the correct formula is, but you need to revisit this. You simply throw away what is the spinbox and use only
position = sh.Shape.Vertexes[vertexIdx].Point
for your calculation. One of these is wrong.Finally, if you are asking how to translate
=IF(self.position=0,0,(IF(self.position=1,1,2)))
into Python that would be:
value = 0 if self.position == 0 else 1 if self.position == 1 else 2
and then you must use
value
somewhere.wrote on 29 Jan 2024, 06:40 last edited by@JonB - Eureka!
I changed the name of the "position" variable on line 2 variable to axis and amended the rest of the code accordingly. Then I replaced the number [2] on lines 44 & 45 with [self.axis]. The spin box slots now alter the output to the 3D model as I was hoping for - see image.
Thank you for you advice and patience - I may be back with some other quandary to solve now that I have had a little success. :)
from PySide.QtGui import * class VertexSelector(QWidget): def __init__(self): super(VertexSelector, self).__init__() ##vars self.depth = 10.0 self.axis = 2 #X=0,Y=1,Z=2 ##Depth object self.lblDepth = QLabel("Depth: Location On Axis") self.sbDepth = QDoubleSpinBox() self.sbDepth.setValue(self.depth) self.sbDepth.setSingleStep(0.5) self.lblAxis = QLabel("Axis: X=0, Y=1, Z=2") self.sbAxis = QSpinBox() self.sbAxis.setValue(self.axis) self.sbAxis.setSingleStep(1) ##button self.btnApply = QPushButton("Apply") self.btnApply.clicked.connect(self.apply) #layout layout = QVBoxLayout() layout.addWidget(self.lblDepth) layout.addWidget(self.sbDepth) layout.addWidget(self.lblAxis) layout.addWidget(self.sbAxis) layout.addWidget(self.btnApply) self.setLayout(layout) ##window self.setWindowFlags(Qt.WindowStaysOnTopHint) self.show() def apply(self): self.depth = float(self.sbDepth.value()) self.axis = (self.sbAxis.value()) shapes = App.ActiveDocument.findObjects("Part::Feature") for sh in shapes: vertexes = [] vertexCount = len(sh.Shape.Vertexes) for vertexIdx in range(vertexCount): try: position = sh.Shape.Vertexes[vertexIdx].Point vertexName="Vertex"+str(vertexIdx+1) App.Console.PrintMessage(vertexName+":") App.Console.PrintMessage(str(round(position[self.axis],2))) if (round(position[self.axis],2) == self.depth): vertexes.append(vertexName) App.Console.PrintMessage("\n") except Exception: App.Console.PrintMessage("Not applicable\n") Gui.Selection.addSelection(sh,vertexes) fselector = VertexSelector()
- Line #1 is the only place you read the spinbox value. And you assign it to
-
1/12