python GUI的麻烦

时间:2014-04-18 01:25:36

标签: python c++ user-interface

我对python不是很好,但对于这个项目,我需要使用python GUI来测试我的程序。它的编译没有任何错误,但是当我在GUI中测试时它会给出错误。该程序的目标是从.txt文件创建一个英语到法语字典,该文件包含所有翻译/定义。我的代码如下。如果有人可以提供帮助,那就太好了。

这些是我得到的错误:

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()

1 个答案:

答案 0 :(得分:1)

错误消息告诉您到底出了什么问题:“未定义全局名称'clearall'”。你必须问自己,“为什么python认为它没有被定义?”在这种情况下,线索是它认为clearall是一个全局函数。为什么?因为这就是你如何使用它。

在查看代码时,您看起来有一个“clerall”方法作为对象的一部分,所以您需要做的就是将clearall(...)更改为self.clearall(...),无论您调用{{1} }}。