1
我不是很好用蟒蛇,但對於這個項目,我需要使用Python的GUI來測試我的節目。它編譯沒有任何錯誤,但它給人錯誤,當我去測試它的GUI。該計劃的目的是從具有所有翻譯/定義.txt文件創建一個英語法語詞典。我的代碼如下。如果任何人都可以提供幫助,那會很棒。麻煩與Python GUI
這是我收到的錯誤:
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1470, in __call__
return self.func(*args)
File "Dictionary.py", line 33, in <lambda>
lambda e, s=self: s.translate(english, french))
File "Dictionary.py", line 69, in translate
clearall(english, french)
NameError: global name 'clearall' is not defined
如需進一步信息,我應該檢查這些條件: 1)沒有命令行參數和2)不成功的文件開口。
Dictionary.cpp:
#include "HashTable.h"
#include "DictionaryEntry.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main(int argc, char** argv)
{
HashTable <DictionaryEntry> table;
DictionaryEntry dictEntry;
string temp;
string entry;
string translation;
vector <string> engWords;
string uentry;
int randNum;
ifstream inputStream;
//If command line is empty, error
if(argc <= 1)
{
cout << "Invalid entry." << endl;
return 0;
}
inputStream.open(argv[1]);
//If no file is opened, error
/*if(!inputStream)
{
cout << "Invalid file." << endl;
return 0;
}*/
while(!inputStream.eof())
{
getline(inputStream, temp);
unsigned location = temp.find_first_of('\t');
entry = temp.substr(0, location);
int end = temp.length();
translation = temp.substr(location + 1, end);
dictEntry.set(entry, translation);
table.insert(dictEntry);
engWords.push_back(entry);
}
while(1)
{
cout << "Insert english word: ";
cin >> uentry;
DictionaryEntry search;
search.set(uentry, "");
if(uentry == "random")
{
randNum = rand() % engWords.size();
temp = engWords.at(randNum);
search.set(temp, "");
dictEntry = table.retrieve(search);
cout << dictEntry.getEntry() << endl;
cout << dictEntry.getTranslation() << endl;
}
else
{
dictEntry = table.retrieve(search);
if(dictEntry.getEntry() != "")
{
cout << dictEntry.getEntry() << endl;
cout << dictEntry.getTranslation() << endl;
}
else
{
cout << "\n";
cout << "\n";
}
}
}
}
List.h:
#ifndef LIST_H
#define LIST_H
using namespace std;
template <typename Object>
class List
{
private:
struct Node
{
Object data;
Node *prev;
Node *next;
Node(const Object & d = Object{ }, Node * p = nullptr, Node * n = nullptr)
: data{ d }, prev{ p }, next{ n } { }
Node(Object && d, Node * p = nullptr, Node * n = nullptr)
: data{ std::move(d) }, prev{ p }, next{ n } { }
};
public:
class const_iterator
{
public:
const_iterator() : current{ nullptr }
{ }
const Object & operator* () const
{ return retrieve(); }
const_iterator & operator++ ()
{
current = current->next;
return *this;
}
const_iterator operator++ (int)
{
const_iterator old = *this;
++(*this);
return old;
}
bool operator== (const const_iterator & rhs) const
{ return current == rhs.current; }
bool operator!= (const const_iterator & rhs) const
{ return !(*this == rhs); }
protected:
Node *current;
Object & retrieve() const
{return current->data;}
const_iterator(Node *p) : current{ p }
{ }
friend class List<Object>;
};
class iterator : public const_iterator
{
public:
iterator()
{ }
Object & operator* ()
{ return const_iterator::retrieve(); }
const Object & operator* () const
{ return const_iterator::operator*(); }
iterator & operator++ ()
{
this->current = this->current->next;
return *this;
}
iterator operator++ (int)
{
iterator old = *this;
++(*this);
return old;
}
iterator operator--()
{
const_iterator::current = const_iterator::current->prev;
return *this;
}
iterator operator--(int)
{
iterator old = *this;
--(*this);
return old;
}
protected:
iterator(Node *p) : const_iterator{ p }
{ }
friend class List<Object>;
};
public:
List()
{ init(); }
~List()
{
clear();
delete head;
delete tail;
}
List(const List & rhs)
{
init();
for(auto & x : rhs)
push_back(x);
}
List & operator= (const List & rhs)
{
List copy = rhs;
std::swap(*this, copy);
return *this;
}
List (List && rhs)
: theSize{ rhs.theSize }, head{rhs.head }, tail{rhs.tail }
{
rhs.theSize = 0;
rhs.head = nullptr;
rhs.tail = nullptr;
}
List & operator= (List && rhs)
{
std::swap(theSize, rhs.theSize);
std::swap(head, rhs.head);
std::swap(tail, rhs.tail);
return *this;
}
iterator begin()
{ return { head->next }; }
const_iterator begin() const
{ return { head->next }; }
iterator end()
{ return { tail }; }
const_iterator end() const
{ return { tail }; }
int size() const
{ return theSize; }
bool empty() const
{ return size() == 0; }
void clear()
{
while(!empty())
pop_front();
}
Object & front()
{ return *begin(); }
const Object & front() const
{ return *begin(); }
Object & back()
{ return *--end(); }
const Object & back() const
{ return *--end(); }
void push_front(const Object & x)
{ insert(begin(), x); }
void push_front(Object && x)
{ insert(begin(), std::move(x)); }
void push_back(const Object & x)
{ insert(end(), x); }
void push_back(Object && x)
{ insert(end(), std::move(x)); }
void pop_front()
{ erase(begin()); }
void pop_back()
{ erase(--end()); }
//Insert x before itr
iterator insert(iterator itr, const Object & x)
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ x, p->prev, p } };
}
//Insert x before itr
iterator insert(iterator itr, Object && x)
{
Node *p = itr.current;
theSize++;
return { p->prev = p->prev->next = new Node{ std::move(x), p->prev, p } };
}
//Erase item at itr
iterator erase(iterator itr)
{
Node *p = itr.current;
iterator retVal{ p->next };
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
theSize--;
return retVal;
}
iterator erase(iterator from, iterator to)
{
for(iterator itr = from; itr != to;)
itr.erase(itr);
return to;
}
iterator find(const Object & x)
{
iterator start= begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
iterator find(string & x)
{
iterator start = begin();
while(start != end()) {
if(strcasecmp(x.c_str(),(*start).getWord().c_str())==0)
return start;
else
start++;
}
return start;
}
*/
const_iterator find(const Object & x) const
{
const_iterator start=begin();
while(start!=end()){
if(x==*start)
return start;
start++;
}
return start;
}
/*
const_iterator find(const string & x){
const_iterator start = const_iterator(head);
while(start != end()){
if(strcasecmp(x.c_str(),(*start).getWord().c_str())==0)
return start;
else
start++;
}
return start;
}
*/
private:
int theSize;
Node *head;
Node *tail;
void init()
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
};
#endif
HashTable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <vector>
#include <string>
#include "List.h"
#include "DictionaryEntry.h"
using namespace std;
//checks if a value is prime
bool isPrime(int n){
if(n==2 || n==3)
return true;
if(n==1 || n%2 == 0)
return false;
for(int i=3; i*i<n; i+=2)
if(n%i == 0)
return false;
return true;
}
//finds the next prime number
int nextPrime (int n) {
if(n%2==0)
n++;
while(!isPrime(n))
n+=2;
return n;
}
template <typename HashedObj>
class HashTable
{
public:
//constructor (explicit so no implicit conversion)
explicit HashTable(int size = 3500) : tableSize(size), currentSize(size), theLists(size) { }
//empty the Hashtable
void makeEmpty()
{
currentSize=0;
//clear each linked list from hastable
for(int i=0; i<tableSize; i++)
theLists[i].clear();
}
//search for x in Hashtable
bool contains(const HashedObj & x) const{
//assign reference variable to rename the complicated object
const List<HashedObj> & whichList = theLists[ myhash(x) ];
//return whether x already exists in the list
return whichList.find(x) != whichList.end();
}
//insert x into Hashtable (true if successful, false if already exists)
bool insert(const HashedObj & x) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash(x) ];
//if x already exists in the list, return false
if(whichList.find(x) != whichList.end())
return false;
//otherwise push to list
whichList.push_front(x);
//rehash if new size is greater than hashtable size
if(++currentSize >tableSize) {
rehash();
}
return true;
}
//remove x from Hashtable (true if successful, false if not found)
bool remove(const HashedObj & x) {
//assign reference variable to rename the complicated object
List<HashedObj> & whichList = theLists[ myhash(x) ];
//iterator is at end of list (i.e., not found)
if(whichList.find(x) == whichList.end())
return false;
//erase x
whichList.erase(whichList.find (x));
--currentSize;
return true;
}
HashedObj & retrieve(HashedObj & obj)
{
return *(theLists[myhash(obj)].find(obj));
}
private:
//The vector of linked-lists hashtable
vector<List<HashedObj> > theLists;
int currentSize;
int tableSize;
//Because coming with new stuff is hard <--Haha
void rehash(){
vector<List<HashedObj> > oldLists=theLists;
int oldtableSize = tableSize;
tableSize = nextPrime(2* oldtableSize);
//Create new double-sized, empty table
theLists.resize(tableSize);
for(int i=0; i<tableSize; i++)
theLists[i].clear();
//copy table over
currentSize = 0;
for(int i=0; i<oldtableSize; i++){
while(!oldLists[i].empty()){
insert(oldLists[i].front());
oldLists[i].pop_front();
}
}
}
//call hash function and makes sure values fit in table
int myhash(const HashedObj & x) const
{
int hashVal = hash2(x); //call hash function
//make sure the hash values fit into HashTable
hashVal %= tableSize;
if(hashVal < 0)
{
hashVal += tableSize;
}
return hashVal;
}
/*
int myhash(const string & x) const
{
int hashVal = hash(x);
hashVal %= tableSize;
if(hashVal < 0)
{
hashVal += tableSize;
}
return hashVal;
}
*/
};
int hash2(const string & key)
{
int hashVal = 0;
for(int i = 0; i < key.length(); i++)
{
hashVal = 37 * hashVal + key[i];
}
return hashVal;
}
int hash2(const DictionaryEntry word)
{
return hash2(word.getEntry());
}
int hash2(int key)
{
return key;
}
#endif
DictionaryEntry.h:
#ifndef DICTIONARYENTRY_H
#define DICTIONARYENTRY_H
#include <string>
#include <iostream>
#include "HashTable.h"
using namespace std;
class DictionaryEntry
{
public:
DictionaryEntry()
{
entry = "";
translation = "";
}
DictionaryEntry(const DictionaryEntry & rhs)
{
entry = rhs.entry;
translation = rhs.translation;
}
void set(string ent, string trans)
{
entry = ent;
translation = trans;
}
const string & getTranslation() const
{
return translation;
}
const string & getEntry() const
{
return entry;
}
bool operator== (const DictionaryEntry & rhs) const
{
return getEntry() == rhs.getEntry();
}
bool operator!= (const DictionaryEntry & rhs) const
{
return (getEntry() != rhs.getEntry());
}
private:
string entry;
string translation;
};
#endif
和Dictionary.py:
#!/usr/bin/python
from Tkinter import *
import subprocess
# general function for frame generation
def frame(root, side):
w = Frame(root)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# general function for button generation
def button(root, side, text, command=None):
w = Button(root, text=text, command=command)
w.pack(side=side, expand=YES, fill=BOTH)
return w
# main class for GUI
class Translator(Frame):
def __init__(self):
Frame.__init__(self)
self.pack(expand=YES, fill=BOTH)
self.master.title("English-French Translator")
self.master.iconname("English-French Translator")
Label(self, text='English').pack(side=TOP, expand=YES, fill=BOTH)
english = StringVar()
Entry(self, relief=SUNKEN, textvariable=english).pack(side=TOP, expand=YES, fill=BOTH)
buttonsF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Translate')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.translate(english, french))
clearF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Clear')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.clearall(english, french))
randF = frame(self, TOP)
btn = button(buttonsF, LEFT, 'Flash Me (TM)')
btn.bind('<ButtonRelease-1>',
lambda e, s=self: s.random(english, french))
Label(self, text='French').pack(side=TOP, expand=YES, fill=BOTH)
french = StringVar()
Message(self, relief=SUNKEN, textvariable=french, width=200).pack(side=TOP, expand=YES, fill=BOTH)
# clear all text boxes
def clearall(self, english, french):
english.set('')
french.set('')
# translate english to french
def translate(self, english, french):
if (len(english.get()) > 0):
try:
# send english word to subprocess
process.stdin.write('%s\n'%english.get())
# read line of output from subprocess (original text)
original=process.stdout.readline()
# read line of output from subprocess (translated text)
translation=process.stdout.readline()
# set english textbox
english.set(original.rstrip())
# set french textbox
french.set(translation.rstrip())
except:
clearall(english, french)
def random(self, english, french):
try:
process.stdin.write('random\n')
original=process.stdout.readline()
translation=process.stdout.readline()
english.set(original.rstrip())
french.set(translation.rstrip())
except:
clearall(english, french)
if __name__ == '__main__':
args='French.txt'
process=subprocess.Popen('Dictionary %s'%args, shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Translator().mainloop()
您需要添加,你得到這個問題的錯誤。 – ebarr
這是_far_代碼太多。在你調試,你應該已經建造了一個_minimal testcase_,張貼經過。 –