How to I fix my code to only access one item in the list on each iteration? - python-3.x

I have been working with pygame for Python these past few days but I have encountered an issue that I can not seem to overcome. First let me talk about the issue and provide the code. The code with the issue is in the WIP branch of my repo. That is were new features are tested before been deployed.
https://github.com/Aeryes/Demented/blob/WIP/menu_testing.py
I have been trying to place my game menus in a class like structure to make it easier to create menus in the future by having a universal class for the menu creation. This has worked except for accessing individual members of my button list located in the menu class. When I check to see if a button is been hovered over to change color the check works but the new color is applied to all buttons in the list not just the one that is been hovered over.
I have tried many things thus far including the following:
I have tried to reference the individual item like this:
--> main_menu.buttons[0].hovered = True
When I do this the code does not work nor does it break the program. It just makes no color change at all.
I have tried to remove the buttons = [] list from the Menu() class and create each button as an individual instance by doing the following:
play_button = main_menu.add_button(button info here)
This just give me a NullType error when I call hovered = True.
I have been using this as a reference for help with this issue:
https://python-forum.io/Thread-PyGame-Creating-a-state-machine
Here is my direct question: How do I get hovering to work for an individual button and not all of them at the same time?
Thank you for your help.

Your problem is here:
if main_menu.buttons[0].rect.collidepoint(pygame.mouse.get_pos()):
Button.hovered = True
else:
Button.hovered = False
You're not setting the hovered flag to true on the actual button, but rather the class (which, as far as I know, doesn't generally serve a function)
To correct it, you should be using
if main_menu.buttons[0].rect.collidepoint(pygame.mouse.get_pos()):
main_menu.buttons[0].hover = True
else:
main_menu.buttons[0].hover = False
The bigger problem is that you never redraw your buttons after the update. The way I solved this (using your preexisting code) was to update your conditional to this:
if main_menu.buttons[0].rect.collidepoint(pygame.mouse.get_pos()):
main_menu.buttons[0].hovered = True
main_menu.buttons[0].draw()
else:
main_menu.buttons[0].hovered = False
main_menu.buttons[0].draw()
There are a couple things to think about.
A for loop iterating over indices would probably be much nicer than three individual conditionals.
You have a bug in your menu class, where you write "for button in buttons:" instead of "for button in self.buttons:"
Finally, you might want to look into your else condition. Given that you're currently recreating your menu continuously, it might not be necessary to un-hover the button, but I'll leave that to you

Related

How to get list of widgets in pyqt?

I am designing a interface with QtDesigner and editing its functionalities with PyQt. One of the widgets that i created has several pushButtons and i want them all to have the property Checkable = True.
So currently what i am doing is:
class MyWidget(QWidget):
def __init__(self):
super(MyWidget, self).__init__()
uic.loadUi('./my_widget.ui', self)
self.pushButton_X.setCheckable(True)
self.pushButton_Y.setCheckable(True)
self.pushButton_Z.setCheckable(True)
self.pushButton_ETC.setCheckable(True)
self.show()
Is there any way i can do something like:
pushbuttons_list = self.get_all_pushbuttons()
for i in pushbuttons_list:
i.setCheckable(True)
?
Im trying the answers to this question but i keep getting
> File "./testing_class.py", line 12, in __init__
items = (self.layout.itemAt(i) for i in range(self.layout.count()))
AttributeError: 'builtin_function_or_method' object has no attribute 'count'
Your example failed because all Qt properties can be accessed by calling the attribute (see the parentheses used for self.layout()):
items = (self.layout().itemAt(i) for i in range(self.layout().count()))
Note that this will only get access to the layout items, not the widgets they might (or might not) contain. For this, using comprehensions will only complicate things unnecessarily, as one-liners should be used only as long as they keep the code readable; the comprehension above is already complex enough, and since you will need to cycle through all items anyway, there's little use in it. Just use a for loop, which is far more readable:
for i in range(self.layout().count()):
widget = self.layout().itemAt(i).widget()
if isinstance(widget, QPushButton):
widget.setCheckable(True)
Note that if you have several buttons that you want checkable and you are doing this only to avoid manually setting the checkable property for all of them, you can just use the extended selection mode that is common for all UI elements that allow selection by keeping pressed Ctrl when clicking multiple objects.
The property editor will automatically show all common properties for the selected widgets, and apply the changed property to all of them.
Another option is to use findChildren():
for button in self.findChildren(QPushButton, Qt.FindDirectChildrenOnly):
button.setCheckable(True)
The Qt.FindDirectChildrenOnly flag is required whenever you have complex layouts that have nested widgets containing other buttons, if you remove that you will find any push button that exists inside the window (or the widget referenced as self).
Finally, buttons can be part of a QButtonGroup, which can also be created in Designer. Just select all buttons (as explained above), right click on one of them and select "Assign to button group", and then:
for button in self.buttonGroup.buttons():
button.setCheckable(True)
Note that the self.buttonGroup above is the object name assigned by Designer, if you change it or you create more than one, ensure that the reference matches it.

Element not recognized

Working on Coded UI testing and for scripts developed using Record Capture and playback feature (ctrl +I).
The problem is when the page has sub-menus (e.g. I need to hover over menu link then click sub-menu). When I record and capture element using Ctrl+I and executed a script it recognizes, but when I ran the script for the second time the element gets changed and it's not recognized.
I have tried simple x path utility posted here but coudn't able to use this feature. What would be the problem for always element id's getting changed. How to resolve it ?
Are you sure it isn't a nested object?
See http://executeautomation.com/blog/how-to-identify-all-the-child-elements-within-a-page-in-coded-ui-test-cuit/
You could also try EnsureClickable()
There could few reasons behind not recognizing an element:
List item Element is not visible when you are trying to click on it.
If Type of Parent Element is e.g. winclient then it’s difficult in coded UI to identify its child elements.
There could various solutions, you can try:
First Click on Menu Item and then click on Sub Menu Item, if you are directly clicking on sub menu item in your recorded script, this will make sub menu element visible.
Also you can check the visibility from Coded UI Test Builder-> Add Assertion button then going to UI Control Map, then select the element in tree and click on Refresh. It will show if element is visible or not.
If Ids are changing, then you can various other properties like Name, ClassName, InnerText, ControlType, TagInstance, ControlName etc. whichever is supported by Element.

"Visible" property on XPages edit boxes based on checkbox selection(s)

I am new to XPages, and I have a Check Box Group ('checkBoxGroup1') as one of my design elements that contains three choices ("CBChoice1", "CBChoice1", "CBChoice1"). Underneath that Check Box Group, I have three edit box fields which correspond to the three checkbox choices. Each time one of the checkbox choices is chosen, I want the corresponding edit box to become visible.
Whenever one of the checkboxes is chosen, I have it partially refreshing the panel that the edit boxes are in, but I cannot figure out the code in each of the edit box's visible property. I started with
getComponent('checkBoxGroup1').getValue() == "CBChoice1"
which kind of works, but isn't the answer. I also tried
var valueArray = getComponent('checkBoxGroup1').getSelectedValues();
valueArray[0] == "CBChoice1";
which seems more on target, but I was getting the following browser error:
Error 500 HTTP Web Server: Command Not Handled Exception
I notice that in the computed code for the visibility property, it is SSJS. I feel like I am close, but have been banging my head for too long. Any help would be greatly appreciated.
A better method might be to bind the checkbox group to either a document data source or a scope variable.
Then, your visible property might look something like:
#Contains(myDoc.getItemValueArray("checkBoxFieldName"),"CBChoice1");
or
#Contains(viewScope.get("checkBoxScopeVar"),"CBChoice1");

I don't want to change color of JButton when pressed

Color newColor = new Color(197,222,90);
JButton newButton;
newButton = new JButton(icon);
newButton.setBacgroundColor(newColor);
When it is pressed it changes color. How can I keep it from changing color? I have multiple buttons, so if there is solution in one or two rows please help me, and keep in mind that I'm beginner, writing some huge classes won't help me, because I have multiple buttons with different names to be affected with this.
EDIT: Solution in one line is:
UIManager.put("Button.select", newColor);
But it changes all button colors but I need another to have different a color.
EDIT2: After some research I figured out there isn't an easy solution (but it should be). How I see it I have 2 solutions, 1. is to break buttons to separate classes and set UIManager for them, and second is to make custom buttons. It is just too much work for button.
I've found nothing that can change that particular behavior on a normal JButton. The problem being, that whatever you write in your actionlistener for the button, will occur AFTER you've let go of the mousebutton, and not "while clicking".
There are workarounds, however.
My preferred choice is, to remove all graphics from the button, and then add your own images to the button's regular and pressed states. You could take a screenshot of your GUI, cut out the button, and set that image to be both states.
JButton myButton = new JButton();
// Sets button x, y, width, height. Make the size match the image.
myButton.setBounds(5, 30, 100, 30);
// Remove border-graphics.
myButton.setBorder(null);
// Remove default graphics from the button
myButton.setContentAreaFilled(false);
// Remove the focus-indicating dotted square when focused (optional)
myButton.setFocusPainted(false);
// Here, myImage is a simple BufferedImage object.
// You can set one like this, provided you have an "images" package,
// next to your main class (ex: com.somecompany.someprogram.images),
// that contains an image:
BufferedImage myImage = ImageIO.read(getClass().getResource("images/myImage.png"));
// Then we simply apply our image to both states for the button, and we're done.
myButton.setIcon(new ImageIcon(myImage));
myButton.setPressedIcon(new ImageIcon(myImage));
Obviously there are many ways to retain and load an image, but since that's not the issue here, I'll leave additional methods out of it.
There's no need to go through it all countless times, though. It should be pretty easy to write your own custom implementation of the JButton class, in which a custom constructor takes a single parameter, being the BufferedImage, and then the constructor sets it up accordingly (changes the icons). Then all you have to do when you create a new JButton, is to use your own class, and pass it an image:
JButton btn = new MyCustomJButton(myImage);
You could also easily get along with very few images. All you need is a HashMap which holds all the images, with a String as a key. Imagine you need 4 OK-buttons. You make a single image of a button with the text "OK" written on it. Then you put that image into the HashMap, like so:
myMap.put("OK", myImage);
Then you could do this when creating a button, over and over again if you'd like more:
JButton btn = new MyCustomJButton(myMap.get("OK"));
Alternatively:
Another way of achieving this, which is pretty elaborate, but probably considered "the right way", is to use ButtonUI, as presented in this answer to another post.
If the OP is referring to the temporary change of background colour on a button with an icon at the moment the mouse is pressed, the following statement does the trick:
button.setContentAreaFilled(false);
"If you wish to have a transparent button, such as an icon only button, for example, then you should set this to false."
This took me a long time to figure out. It seems to be a little known technique, perhaps since its name gives little clue as to its effect.
With only first lane we can still see that it is clicked. You need to combine those two:
button1.setContentAreaFilled(false);
button1.setEnabled(false);
and if you don't wanna in grey color you put another button under him.
panelname.add(button1,+5,+5); \\(first not clicable, not visible button, notice +5)
panelname.add(button2,-5,-5); \(-5,-5 means it is 5 points under panel)

Watir : How do we capture the subitems displayed by doing mouseover on a particular item

I am trying to work with mouseover on a particular Item in my application by using the following command
{
ie.text_field(:xpath, "//a[contains(text(),'Deal')]").fire_event('onmouseover')
}
On doing mouseover on a item, two subitems are displayed.
Is there any way to capture the sub items which are part of the Item by doing mouseover with which we can report that our test is pass or fail.
Please suggest.
Additional Information :
If we take example,On the StackOver flow page, If i do mouseover on my name, i get a window where i see activity, privileges, Logout and other stuff. This is really what i was looking for. Is there a way to capture the items displayed on the window on doing mouseover.
I also tried to capture the subitems with the following :
{
text=ie.text_field(:xpath, "//a[contains(text(),'Deal')]").fire_event('onmouseover')
puts(text.inspect)
}
On doing this "text" value is displayed as 'nil'.
My general tactic for such things is a combination of using IRB and the IE Developer tool, or Firebug.
using IRB, type out (or cut and paste) the watir statement to fire the onmouseover command to the proper element on the page.
Then have the developer tool rescan the DOM (there's a little refresh icon you can click) The use the tool to point to an element to point to one of the items in the stuff exposed by the onmouseover. Using the info from that, you can then figure out how to address those elements to get the text from the proper div, etc.
If I do that here to the info that opens up when I float the mouse over my name I can find out that it is a table of class "profile-recent-summary" Furthermore I can then look at the way the table is made up and see for example that the 'today' reputation value is in the second cell on that row.. The row also has the text 'reputation' in it.. so
browser.table(:class, 'profile-recent-summary').row(:text, /reputation/).cell(:index, 2).flash
Should flash the cell I want (index might be 1 if using firewatir or webdriver) I can then replace the .flash with something else like .text if I want to get the text from that cell (which is actually inside a link that sits in the cell)..
without seeing your code, I would 'inspect' the element that you are trying to verify and when_present (text) assert that its true

Resources