I'm trying to construct a game where you can play five-in-row and when someone wins I want the label to change from like "Game is going on" to "Player 1 won" and this is where I am stuck.
The way I have constructed it all is like this. I have one class for the graphics (a Frame) and I have one class for all the Buttons that you can click on to set it to "X" or "O". And then I have one last class that checks if the grid has five of some value in a row, and that one runs after each successful click.
The label is of course set in the Frame class and first I had it like this just to make sure that I could see something
def __init__(self, master = None, rows = 10, cols = 10):
Frame.__init__(self, master)
Some other selfs....
self.inforad = Label(master, text = "Game is going on")
and this prints out nicely, just like I want it. Now I have been trying for hours to make this change when someone wins and I just can't make it work! The last thing I tried is to use the StringVar() and I did it like this
self.info = StringVar()
self.info.set("Game is going on")
self.inforad = Label(master, text = self.info)
and for starter this doesn't work at all, it prints out PY_VAR0. My plan was to define a method to call this during the game, like this
def disp(self, string):
self.info.set(string)
return self.info
And this doesn't work at all. Can someone help me with this? I am really new to programming, did my first code for like 3 weeks ago.
(If self.inforad is placed within the Frame subclass instance, self, its master should be self, not the master of self.)
As for your specific question, change Label(master, text = self.info) to Label(self, textvariable = self.info).
Related
Very simple. Cell A1 has an image in it, which I supply through Insert:Picture:From File...
Now I want Cell A3 to automatically show the same picture. I simply can't find a way-- certainly the "=" doesn't work. At this point, I don't care if the images are "links" or embedded, I just want it to work. Can it? Thx.
Edit, 09-01-17, based on Jim K's idea, here's macro code I have installed:
REM ***** BASIC *****
Private oListener as Object
Private cellA1 as Object
Sub AddListener
Dim Doc, Sheet, Cell as Object
Doc = ThisComponent
Sheet = Doc.Sheets.getByName("Sheet1")
cellA1 = Sheet.getCellrangeByName("A1")
'create a listener
oListener = createUnoListener("Modify_","com.sun.star.util.XModifyListener")
'register the listener
cellA1.addModifyListener(oListener)
End Sub
Sub Modify_disposing(oEv)
End Sub
Sub RmvListener
cellA1.removeModifyListener(oListener)
End Sub
' macro jumps here when oListener detects modification of Sheet
Sub Modify_modified(oEv)
Doc = ThisComponent
Sheet = Doc.Sheets.getByIndex(0)
originCell = Sheet.getCellByPosition(0,0)
originValue = originCell.Value
if originValue then
print "originValue is " & originValue
else
print "originValue zero"
end if
End Sub
The problem, ironically, is that it works. It works for integers and {non-value}, I mean an empty cell.
So any integer not zero prints TRUE, zero prints FALSE, and empty cell prints FALSE.
But that's where it quits working-- any kind of string "asdf" also returns FALSE.
Maybe that could be fixed, but there's something a lot worse: When I paste an image in the cell, or use the Insert/Image/From File... menu, or Cut an existing image... Nothing happens! The Sheet Modified business does not trigger the expected routine.
Any hope? Thx.
As you discovered, the solution in my comment does not work, because the Content changed event will not trigger when images are added. I looked into other events as well, but they did not work either.
So instead, we can set up a function that runs periodically. Each time it runs, it checks the count of images, and if any have been added or removed, it calls update_copied_images() below, which currently simply reports the value of cell A1, as in your code.
As explained here, I have not gotten a timer loop to work in Basic without crashing, so we can use Python instead (a better language, so this is not a drawback in my opinion).
import time
from threading import Thread
import uno
COLUMN_A, COLUMN_B, COLUMN_C = 0, 1, 2
FIRST_ROW = 0
def start_counting_images(action_event=None):
t = Thread(target = keep_counting_images)
t.start()
def keep_counting_images():
oDoc = XSCRIPTCONTEXT.getDocument()
oSheet = oDoc.getSheets().getByIndex(0)
oDrawPage = oSheet.getDrawPage()
messageCell = oSheet.getCellByPosition(COLUMN_C, FIRST_ROW)
messageCell.setString("Starting...")
prevCount = -1
while hasattr(oDoc, 'calculateAll'): # keep going until document is closed
count = oDrawPage.Count
if prevCount == -1 or prevCount != count:
prevCount = count
messageCell.setString("Number of Images: " + str(prevCount))
update_copied_images(oSheet)
time.sleep(1)
def update_copied_images(oSheet):
originCell = oSheet.getCellByPosition(COLUMN_A, FIRST_ROW)
originString = originCell.getString()
messageCell = oSheet.getCellByPosition(COLUMN_B, FIRST_ROW)
if len(originString):
messageCell.setString("originString '" + originString + "'")
else:
messageCell.setString("originString length is zero")
g_exportedScripts = start_counting_images,
To run, go to Tools -> Macros -> Run Macro, find the .py file under My Macros where you put this code, and run start_counting_images.
Folks,
So I've been working on a little GUI using Tkinter for a capstone project, and given the circumstances, I've only been programming for about two weeks before I was thrown into this, so I'm still a newbie.
My issue today is that I cannot manage to get my checkbutton dictionary to update values; the output for my checkbutton is always 0 or False. The code is as follows:
...
datatype= {'Joint Angle' : 0,
'Joint Acceleration' : 0,
'Ground Reaction Force' : 0,
'Muscle Activation' : 0
}
for measure in datatype:
datatype[measure] = IntVar()
dt_cb = Checkbutton(root, text=measure,
variable=datatype[measure],command = enable_location_state)
dt_cb.grid(column=0, sticky='W', padx=20)
dt1 = datatype['Joint Angle'].get()
dt2 = datatype['Joint Acceleration'].get()
dt3 = datatype['Ground Reaction Force'].get()
dt4 = datatype['Muscle Activation'].get()
...
So I tried periodically printing values throughout the code and I continued to get 0 as soon as I booted the GUI, and after that, no matter what I clicked, the numbers did not update. I read that I should try BooleanVar() and StringVar() instead, but neither of those worked. The code is based off of another bit of code I found somewhere on stackoverflow, though I cannot remember exactly where.
I tried making it a list rather than a dictionary in order to overcome my problem because I was successful with lists previously, but the list created only a single checkbutton for all of those and I was unable to differentiate what is what.
The command enable_location_state configures other checkbuttons, and is as follows:
def enable_location_state():
if dt1 == 1 or dt2 == 1:
ja_cb.configure(state=ACTIVE)
if dt3 == 1:
grf_cb.configure(state=ACTIVE)
if dt4 == 1:
emg_cb.configure(state=ACTIVE)
Your problem is that you are getting the values of the IntVar only once: at the same moment you create your buttons. Move your .get() statements to the beginning of the enable_location_state() function. That way, every time your checkbutton is clicked, the function will check on (i.e., .get()) the value of the IntVar.
I've been working in a code for some weeks, just trying to start with python and I've found a strange problem when I try to update the values in a top level window from Tk, the previous value of the label seems to be in the background of the label and I must remove it, here some pics to show the problem, thank you for reading my problem and also for all your help.
link to the pic:
http://oi57.tinypic.com/e6u2c2.jpg
PD: it is in spanish
PD2: if the code is needed I can paste the segments of the code that generates this issue.
The problem was generated when I hitted a button in the Tkinter interface, and every time it generated a new Label, this new Label displayed the updated information, but the older ones was still in the frame, then when I changed the value of the StringVar to something shorter I still could see the last Label there, the solution was to destroy the last Label when I update the value of the StringVar socitaed to the Label, then I get what I needed.
The code that generated the error:
self.varTotal = StringVar()
self.lblTotal = Label(self.master, textvariable = self.varTotal)
self.varTotalLetras = StringVar()
self.lblTotalLetras = Label(self.master, textvariable = self.varTotalLetras)
...
self.varTotal.set(total)
self.varTotalLetras.set(num2words(int(total), lang = 'es').upper() + " PESOS.")
Then every time when I clicked the button a new instance of the Label seemed to be created.
And My solution was to delete the current instance of the Labels and then create another one.
I'm building a python class to encapsulate a drop-down list and its buttons in one convenient widget and I ran across a problem.
class DropDownMenu(DropDown):
def __init__(self, **kwargs):
super(DropDownMenu, self).__init__(**kwargs)
self.The_Menu = DropDown()
self.The_Btns = []
self.Num_Btns = 0
def Set_Num_Btns(self):
self.Num_Btns = len(self.The_Btns)
def Create_Menu(self, Btn_Names):
# Populate List Size Property
if (self.Num_Btns == 0):
self.Set_Num_Btns()
# Add Buttons to the Drop-Down
for i in range(0, self.Num_Btns):
self.The_Btns.append(Button(text = Btn_Names[i], size_hint_y = None, height = 20))
self.The_Menu.add_widget(self.The_Btns[i])
It compiles fine and when I try to create a drop-down menu, I get what I want:
self.File_Menu = DropDownMenu()
self.File_Menu.Create_Menu(self.File_Menu_Names)
self.add_widget(self.File_Menu)
But, if I try to bind any of the buttons to anything, like so:
self.File_Menu.The_Btns[0].bind(on_release = self.Insert_File_Menu.open)
The compiler throws an exception saying the list was out-of-bounds. On further inspection, I realized that even though I'm calling the Create_Menu function, the value of The_Btns is not being changed from an empty list. So, my question is: how do I fix this problem?
Any help would be appreciated. Thanks!
First of all, python doesn't "compile" in the sense that you refer to, and doesn't have a compiler. Also, have a look at PEP8.
To answer your question, You are iterating over a range, 0 to Num_Btns. However, in Set_Num_Btns, you set the variable to len(self.The_Btns), which is an empty list, i.e. you are iterating over range(0, 0). I suspect you mean to do soemthing like this:
for name in Btn_Names:
self.The_Btns.append(Button(text=name, ...))
....
I use the following methods to create a cell and populate data in it(adapted from the tweets app example)
Now I want to add a new label displaying the selected event date and a button that will perform another action.
Here comes the 2 methods:
def self.cellForEvent(event, inTableView:tableView)
cell = tableView.dequeueReusableCellWithIdentifier(EventCell::CellId) || EventCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier:CellId)
cell.fillWithEvent(event, inTableView:tableView)
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton
cell
end
Populate data into the cell
def fillWithEvent(event, inTableView:tableView)
self.textLabel.text = event.name
puts event.image
unless event.image
self.imageView.image = nil
Dispatch::Queue.concurrent.async do
event_image_data = NSData.alloc.initWithContentsOfURL(NSURL.URLWithString(event.image_url))
if event_image_data
event.image = UIImage.alloc.initWithData(event_image_data)
Dispatch::Queue.main.sync do
self.imageView.image = event.image
tableView.delegate.reloadRowForEvent(event)
end
end
end
else
self.imageView.image = event.image
end
end
railsdog's recommendation is not without merit. You could make a #reference to the cell you want to edit, and make changes to it later. But this is kind of dangerous - lots of pitfalls: What happens it the cell is moved off screen? Reused elsewhere? Tricky.
Instead, I would recommend adding some of the fillWithEvent:inTableView code into the cellForEvent method, that way you can call tableView.reloadRowsAtIndexPaths:withRowAnimation: and that method will be called. This moves the complications I mentioned above onto the back of the Cocoa framework, and that's a good thing :-)
The downside is that you'll need to keep the indexPath handy (or calculatable), and always keep in mind that the event associated with the cell is transient, because the cells are reused. Your code above doesn't seem to keep a reference to event, which is a good thing!
# in fetchImageForEvent:tableView:
# ...
event.image = UIImage.alloc.initWithData(event_image_data)
Dispatch::Queue.main.sync do
# instead of this:
# self.imageView.image = event.image
# tell the tableView to reload. unfortunately, we don't have the index
# path. not sure how you're calculating it, but if you've got a list of
# events, this should be easy.
# I'm just assuming section 0, row 1 here.
path = NSIndexPath.indexPathWithIndex(0).indexPathByAddingIndex(1)
tableView.reloadRowsAtIndexPaths([path], withRowAnimation:UITableViewRowAnimationAutomatic)
end